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; }
懶加載 java
//懶加載 //定義的文本順序不用多考慮,由於初始化是按需的 //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; }
抽象類型ide
錯誤寫法ui
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方法,由於參數類型不一樣 }
正確寫法blog
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){} }