【正文】
s should be smart enough to realize that 2over4 is the same as 1over2, and convert it accordingly before adding the two together. 4 This is the purpose of the nested private gcd() function and g value inside of the Rational class. When the constructor is invoked in Scala, the entire body of the class is evaluated, which means g will be initialized with the greatest mon denominator of n and d, and then used in turn to set n and d appropriately. Looking back at Listing 1, it39。ll point it out. Scala has class(es), too Rather than embark on a lengthy and abstract discussion of the class features that Scala supports, let39。ll see some interesting tidbits related to class definitions and usage in Scala. In last month39。s article , you saw just a touch of Scala39。s look at a definition for a class that might be used to bring rational number support to the Scala platform (largely swiped from Scala By Example see Resources): Listing 1. class Rational(n:Int, d:Int) { private def gcd(x:Int, y:Int): Int = { if (x==0) y else if (x0) gcd(x, y) else if (y0) gcd(x, y) 2 else gcd(y%x, x) } private val g = gcd(n,d) val numer:Int = n/g val denom:Int = d/g def +(that:Rational) = new Rational(numer* + *denom, denom * ) def (that:Rational) = new Rational(numer * * denom, denom * ) def *(that:Rational) = new Rational(numer * , denom * ) def /(that:Rational) = new Rational(numer * , denom * ) override def toString() = Rational: [ + numer + / + denom + ] } While the overall structure of Listing 1 is lexically similar to what you39。s also fairly easy to see that I created an overridden toString method to return the values of Rational, which will be very useful when I start exercising it from the RunRational driver code. Notice the syntax around toString, however: the override keyword in the front of the definition is required so that Scala can check to make sure that a corresponding definition exists in the base class. This can help prevent subtle bugs created by accidental keyboard slips. (It was this same motivation that led to the creation of the Override annotation in Java 5.) Notice, as well, that the return type is not specified it39。s new with you? The everything is a function rule has two powerful effects: The first, as you39。 private int numer。 public Rational $plus(Rational)。 thus far, I have been lax in exercising this rule for my Scala code, so let?s see what 8 happens when you put this Rational class inside of a traditional JUnit test suite, as shown in Listing 10: Listing 10. import .*。 // 1 because of gcd() invocation during construction。s used in nested and anonymous nested class names). In order to invoke those methods, you either have to write the tests in Groovy or JRuby (or some other language that doesn39。 } public void setFirstName(String value) { 10 = value。 private int age。本文是 面向 Java開發(fā)人員的 Scala指南 系列 的第二期 , 作者 Ted Neward遵循對一種語言進(jìn)行評價的基本前提:一種語言的威力可以直接通過它集成新功能的能力衡量,在本文中就是指對復(fù)數(shù)的支持。記住,其中的一些特性并不是直接對應(yīng),或者說,在某些情況下, “對應(yīng) ” 更像是一種類比,而不是直接的對應(yīng)。如果要將 1/2與 2/4相加,那 Rational 類應(yīng)該足夠聰明,能夠認(rèn)識到 2/4和 1/2是相等的,并在將這兩個數(shù)相加之前進(jìn)行相應(yīng)的轉(zhuǎn)換。 一些重要值 接下來分別是 numer 和 denom的定義。 當(dāng)然還有一個問題,如何操縱 Rational 呢?與 ,不能直接修改現(xiàn)有的 Rational 的值,所以惟一的辦法是根據(jù)現(xiàn)有類的值創(chuàng)建一個新 的 Rational,或者從頭創(chuàng)建。 在 Rational 類中,為有理數(shù)定義了 4種操作。例如,假設(shè)提供一個 “求倒數(shù) ”操作符 , 這個操作符會將分子和分母調(diào)換 , 返回一個新的 Rational(即對于 Rational(2,5)將返 回 Rational( 5, 2)) 。如果您需要證據(jù),那么只需注意編譯器生成以 0xCAFEBABE開頭的 .class 文件,就像 javac一樣。 public Rational $times(Rational)。 public int $tag()。 assertTrue(() == 5)。 //r1.$plus(r2)。我采用后一種方法,從 Scala的角度看這不是那么有趣,但是如果您有興趣的話,可以看看本文的代碼中包含的結(jié)果(參見 下載 )。 } public void setFirstName(String value) { = value。 private int age。但是,由于原始的 Person沒有與這些可變 setter 相關(guān)的同步代碼,所以 Scala 版本使用起來更安全。 } public void setLastName(String value) { = value。 “更好的 ” Java 我學(xué)習(xí) C++的時候 Bjarne Stroustrup 建議,學(xué)習(xí) C++的一種方法是將它看作 “更好的C語言 ”(參見 參考資料 )。 assertTrue(() == 15)。 assertTrue(() == 0)。類中定義了兩個構(gòu)造函數(shù):一個構(gòu)造函數(shù)帶有一個 int參 數(shù),另一個帶有兩個 int參數(shù)。 public Rational $plus(Rational)。 private int numer。因此,該語法將顛覆大多數(shù)對象語言中常見的傳統(tǒng) reference thenmethod語法。每種操作以它的數(shù)學(xué)符號命名: +、 、 * 和 /。 與其外表相反,這并非操作符重載。 16 在形式上, Scala 調(diào)用無參數(shù)的 numer 和 denom方法 , 這種方法用于創(chuàng)建快捷的語法以定義 accessor。在 Scala中調(diào)用構(gòu)造函數(shù)時,將對整個類進(jìn)行計算,這意味著將 g初始化為 n和 d的最大公分母,然后用它依次設(shè)置 n和 d。 Scala和 Java一樣使用類 我們不對 Scala支持的類特性作冗長而抽象的討論,而是著眼于一個類的定義,這個類可用于為 Scala平臺引入對有理數(shù)的支持(主要借鑒自 “Scala By Example”,參見 參考資料 ): 清單 1. class Rational(n:Int, d:Int) { private def gcd(x:Int, y:Int): Int = { if (x==0) y else if (x0) gcd(x, y) else if (y0) gcd(x, y) else gcd(y%x, x) } private val g = gcd(n,d) val numer:Int = n/g val denom:Int = d/g 14 def +(that:Rational) = new Rational(numer* + *denom, denom * ) def (that:Rational) = new Rational(numer * * denom, denom * ) def *(that:Rational) = new Rational(numer * , denom * ) def /(that:Rational) = new Rational(numer * , denom * ) override def toString() = Rational: [ + numer + / + denom + ] } 從詞匯上看,清單 1的整體結(jié)構(gòu)與 Java代碼類似,但是 , 這里顯然還有一些新的元素。 在上一期 文章 中,您只是稍微了解了一些 Scala 語法,這些是運行 Scala 程序和了解其簡單特性的最基本要求。t a plete dropin replacement, given that the original Person had some mutable setters. But considering the original Person also had no synchronization code around those mutable setters, the Scala version is safer to use. Also, if the goal is to truly reduce the number of lines of code in Person, you could remove the getFoo property methods entirely because Scala will generate accessor methods around each of the constructor parameters firstNa