Scala中的Class操作
我們建立一個Rational類:建立一個Rational,進行除法計算
構造一個Rational
如果一個類沒有一個body,你不需要指定空的花括號(雖然你可以,當然,如果你想)。 後面括號中的識別符號n和d
類名Rational稱為類引數。 Scala編譯器將收集這兩個類引數並建立一個主要建構函式,它採用相同的兩個引數
class Rational(n : Int,d: Int)
scala和java中不一樣,構造引數可以直接這樣寫,java中有建構函式和引數
class Rational(n : Int,d: Int){
println("Create " + n + "/" + d)
//我們作為除法的分母,不能為0,我們可以這樣去限制D的值。如果為0的話,將丟擲相關的錯誤資訊
//require方法將返回一個boolean的值,如果返回為true,則可以使用,如果為false將丟擲java.lang.IllegalArgumentException: requirement failed的異常
require(d != 0)
//定義私有變數和方法 將66/42變為11/7
private val g = gcd(n.abs,d.abs)
//定義兩個欄位
val numer: Int = n / g
val denom: Int = d / g
//這個相當於java中的程式碼:private int numer; private int denom; public Rational(int n,int d){this.numer=n,this.denom = d}
//重新去實現toString的方法
override def toString = numer + "/" + denom
//定義一個add的方法,如果我們這樣訪問n和d的時候回報錯,因為這兩個引數在add方法裡面訪問不到,
//我們需要定義兩個欄位,就像java一樣,構造器的方法引數不能用在別的方法上面是一樣的道理
// def add(that: Rational) : Rational = new Rational(n * that.d + that.n * d , d * that.d)
def add(that: Rational) : Rational
= new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
//引用自己:關鍵字this指的是呼叫當前正在執行的方法的物件例項,或者在建構函式中使用的物件例項
//this.numer指呼叫lessThan的物件的分子。你也可以省略這個字首,只寫numer;這兩個符號是等價的
def lessThan(that: Rational) =
this.numer * that.denom < that.numer * this.denom
def max(that: Rational) =
if(this.lessThan(that)) that else this
//輔助建構函式
//有時你需要在一個類中有多個建構函式。 在Scala中,除主要建構函式之外的建構函式稱為輔助建構函式
// 在Scala中,每個輔助建構函式都必須呼叫另一個建構函式與第一個動作相同的類。
//換句話說,每一箇中的第一個陳述每個Scala類中的輔助建構函式都將具有“this(...)”形式。
//被呼叫的建構函式是主建構函式(如在Rational中)示例),或者在文字之前出現的另一個輔助建構函式呼叫建構函式。
//這個規則的淨效果是Scala中的每個建構函式呼叫最終都會呼叫它的主要建構函式類。 因此,主建構函式是類的單個入口點
//輔助建構函式的定義
def this(n: Int) = this(n,1) //這是一個輔助建構函式
private def gcd(a: Int,b: Int): Int =
if(b == 0) a else gcd(b,a % b)
//定義相關的操作
def +(that: Rational): Rational
= new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
def *(that: Rational): Rational
= new Rational(
numer * that.numer,denom * that.denom
)
def -(that: Rational): Rational
= new Rational(
numer * that.denom - that.numer * denom,
denom * that.denom
)
def /(that: Rational): Rational
= new Rational(
numer * that.denom,denom * that.numer
)
//進行方法過載
def +(i: Int): Rational =
new Rational(numer + i * denom,denom)
def *(i: Int): Rational =
new Rational(numer * i,denom)
def -(i: Int): Rational =
new Rational(numer - i * denom,denom)
def /(i: Int): Rational =
new Rational(numer,denom * i)
//進行隱式轉換 implicit
//正如本章所示,使用運算子名稱和方法建立方法定義隱式轉換可以幫助您為哪個客戶端設計庫程式碼簡潔易懂。
//Scala為您提供了強大的力量設計這樣易於使用的庫,但請記住,有電源有責任。如果使用不當,
//運算子方法和隱式轉換都可以產生難以閱讀和理解的客戶端程式碼。 因為隱式轉換是由編譯器隱式應用的,
//而不是在原始碼中明確寫下來的,所以對於客戶端程式設計師來說這是不明顯的正在應用什麼隱式轉換。
//雖然運算子方法通常會使客戶端程式碼更簡潔,但它們只會使它更多客戶端程式設計師能夠識別並記住每個操作符的含義。
//在設計庫時,您應該牢記的目標不僅僅是實現簡潔的客戶端程式碼,但可讀,可理解的客戶端程式碼。
//簡潔性通常是可讀性的重要組成部分,但是你可以把它簡潔得過分。 通過設計圖書館,
//使其具有高雅的簡潔性同時可理解的客戶端程式碼,您可以幫助那些客戶端程式設計師高效地工作
implicit def intToRational(x: Int) = new Rational(x)
建立一個RationalRun.scala程式啟動:
object RationalRun extends App{
val oneHalf = new Rational(1,2)
val twoThirds = new Rational(2,3)
println("oneHalf:" + oneHalf)
println("twoThirds:" + twoThirds)
println("new Rational(1,2):" + new Rational(1,2))
// println("分母不能為0:" + new Rational(5,0)) //這裡將丟擲一個錯誤:java.lang.IllegalArgumentException: requirement failed
println("oneHalf add twoThirds:" + (oneHalf add twoThirds))
//獲取相應的欄位資訊
println("oneHalf.numer:" + oneHalf.numer)
println("oneHalf.denom:" + oneHalf.denom)
//比較oneHalf和twoThirds的大小,this就是oneHalf that就是傳過去的引數 twoThirds
println("oneHalf max twoThirds:" + oneHalf.max(twoThirds))
println("輔助建構函式的使用:" + new Rational(5))
//定義私有變數和方法
println("定義私有變數和方法:" + new Rational(66,42))
//定義操作方法
val x = new Rational(12,5)
val y = new Rational(4,3)
println("進行+操作:" + (x + y)) //相當於x.+(y)
println("進行*操作:" + (x * y)) //相當於x.*(y)
println("進行方法過載 x*2:" + (x * 2))
//println("進行隱式轉換:" + (2 * x))
}
編譯上面的兩個類:
執行RationalRun