package com.evor.test1 class Test1 { } object Test1{ def main(args:Array[String]):Unit = { //类参数和抽象字段的初始化顺序并不一致 //抛出异常的原因:RationalTrait初始化的时候,denonArg仍然为0 /* val r1 = new RationalTrait{ val numerArg=50; val denomArg=60; } */ //解决方案:预初始化字段。在调用超类之前初始化子类字段 val r2 = new { val numerArg=50; val denomArg=60; }with RationalTrait } } //解决方案:预初始化字段。在调用超类之前初始化子类字段 object twoThirds extends { val numerArg = 2; val denomArg = 3; }with RationalTrait //解决方案:预初始化字段。在调用超类之前初始化子类字段 //类定义中的预初始化字段 class RationalClass (n:Int,d:Int) extends{ val numerArg = n; val denomArg = d; }with RationalTrait{ def + (that:RationalClass) = new RationalClass ( numer *that.denom +that.numer*denom, denom*that.denom) } trait RationalTrait{ val numerArg:Int ; val denomArg:Int ; require(denomArg!=0); private val g = gcd(numerArg,denomArg) val numer = numerArg/g val denom = denomArg/g private def gcd(a:Int,b:Int):Int={ if(b==0) a else gcd(b,a%b) } override def toString = numer+"/"+denom; }
懒加载
//懒加载 //定义的文本顺序不用多考虑,因为初始化是按需的 //g将在numer和denom之前完成初始化 trait RationalTrait{ val numerArg:Int ; val denomArg:Int ; lazy val numer = numerArg/g lazy val denom = denomArg/g lazy private val g = { require(denomArg!=0); gcd(numerArg,denomArg) } private def gcd(a:Int,b:Int):Int={ if(b==0) a else gcd(b,a%b) } override def toString = numer+"/"+denom; }
抽象类型
错误写法
class Food abstract class Animal{ def eat(food:Food) } class Grass extends Food class Cow extends Animal{ override def eat(food:Grass){} //cow类的eat方法不能重写animal类的eat方法,因为参数类型不同 }
正确写法
class Food abstract class Animal{ type SuitableFood <:Food //类型有上界约束 Food def eat(food:SuitableFood) } class Grass extends Food class Cow extends Animal{ type SuitableFood = Grass override def eat(food:Grass){} }