在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Scala/ 類(lèi)和對(duì)象 (四)
包對(duì)象
Ordered Trait
組合和繼承–定義 final 成員
基本數(shù)據(jù)類(lèi)型
Match 表達(dá)式
類(lèi)和對(duì)象 (三)
操作基本數(shù)據(jù)類(lèi)型
for 表達(dá)式
組合和繼承–重載成員函數(shù)和方法
類(lèi)和對(duì)象 (二)
組合和繼承–定義 factory 對(duì)象
組合和繼承–多態(tài)和動(dòng)態(tài)綁定
Trait 的基本概念
if 表達(dá)式
組合和繼承–抽象類(lèi)
函數(shù)–函數(shù)字面量的一些簡(jiǎn)化寫(xiě)法
while 循環(huán)
組合和繼承–使用組合還是繼承?
訪問(wèn)控制修飾符
Trait 示例–Rectangular 對(duì)象
組合和繼承–定義參數(shù)化成員變量
組合和繼承–定義無(wú)參數(shù)方法
類(lèi)和對(duì)象 (一)
函數(shù)–閉包
函數(shù)–類(lèi)成員函數(shù)
Scala 基本數(shù)據(jù)類(lèi)型的實(shí)現(xiàn)方法
try 表達(dá)式處理異常
選擇瘦接口還是胖接口設(shè)計(jì)?
組合和繼承–小結(jié)
創(chuàng)建新的控制結(jié)構(gòu)
使用 import
為訪問(wèn)控制修飾符添加作用域
Scala 的類(lèi)層次關(guān)系
類(lèi)和對(duì)象 (五)
傳名參數(shù)
柯里化函數(shù)
函數(shù)–頭等公民
組合和組合和繼承–定義 heighten 和 widen 函數(shù)
使用 Package–將代碼放入包中
隱含的 import
所有類(lèi)的公共子類(lèi)–底層類(lèi)型
進(jìn)一步 Scala
函數(shù)–局部函數(shù)
引用包中的代碼
組合和繼承–使用 override 修飾符
組合和繼承–實(shí)現(xiàn)類(lèi) Element 的 above,beside 和 toString()方法
類(lèi)和對(duì)象 (四)
函數(shù)–尾遞歸
沒(méi)有“break”和“continue”的日子
組合和繼承–調(diào)用基類(lèi)構(gòu)造函數(shù)
減低代碼重復(fù)
函數(shù)–函數(shù)–可變參數(shù),命名參數(shù),缺省參數(shù)
起步 Scala
組合和繼承–擴(kuò)展類(lèi)
函數(shù)–部分應(yīng)用的函數(shù)
開(kāi)始神奇的 Scala編程之旅
組合和繼承–概述
Trait 用來(lái)實(shí)現(xiàn)可疊加的修改操作

類(lèi)和對(duì)象 (四)

添加成員變量

本篇繼續(xù)上一篇,前面我們定義了 Rational 的主構(gòu)造函數(shù),并檢查了輸入不允許分母為 0。下面我們就可以開(kāi)始實(shí)行兩個(gè) Rational 對(duì)象相加的操作。我們需要實(shí)現(xiàn)的函數(shù)化對(duì)象,因此 Rational 的加法操作應(yīng)該是返回一個(gè)新的 Rational 對(duì)象,而不是返回被相加的對(duì)象本身。我們很可能寫(xiě)出如下的實(shí)現(xiàn):

class Rational (n:Int, d:Int) {
   require(d!=0)
   override def toString = n + "/" +d
   def add(that:Rational) : Rational =
     new Rational(n*that.d + that.n*d,d*that.d)
}

實(shí)際上編譯器會(huì)給出如下編譯錯(cuò)誤:

<console>:11: error: value d is not a member of Rational
            new Rational(n*that.d + that.n*d,d*that.d)
                                ^
<console>:11: error: value d is not a member of Rational
            new Rational(n*that.d + that.n*d,d*that.d)

這是為什么呢?盡管類(lèi)參數(shù)在新定義的函數(shù)的訪問(wèn)范圍之內(nèi),但僅限于定義類(lèi)的方法本身(比如之前定義的 toString 方法,可以直接訪問(wèn)類(lèi)參數(shù)),但對(duì)于 that 來(lái)說(shuō),無(wú)法使用 that.d 來(lái)訪問(wèn) d. 因?yàn)?that 不在定義的類(lèi)可以訪問(wèn)的范圍之內(nèi)。此時(shí)需要定類(lèi)的成員變量。(注:后面定義的 case class 類(lèi)型編譯器自動(dòng)把類(lèi)參數(shù)定義為類(lèi)的屬性,這是可以使用 that.d 等來(lái)訪問(wèn)類(lèi)參數(shù))。

修改 Rational 定義,使用成員變量定義如下:

class Rational (n:Int, d:Int) {
   require(d!=0)
   val number =n
   val denom =d 
   override def toString = number + "/" +denom 
   def add(that:Rational)  =
     new Rational(
       number * that.denom + that.number* denom,
       denom * that.denom
     )
}

要注意的我們這里定義成員變量都使用了 val ,因?yàn)槲覀儗?shí)現(xiàn)的是“immutable”類(lèi)型的類(lèi)定義。number 和 denom 以及 add 都可以不定義類(lèi)型,Scala 編譯能夠根據(jù)上下文推算出它們的類(lèi)型。

scala> val oneHalf=new Rational(1,2)
oneHalf: Rational = 1/2
scala> val twoThirds=new Rational(2,3)
twoThirds: Rational = 2/3
scala> oneHalf add twoThirds
res0: Rational = 7/6
scala> oneHalf.number
res1: Int = 1

可以看到,這是就可以使用 .number 等來(lái)訪問(wèn)類(lèi)的成員變量。

自身引用

Scala 也使用 this 來(lái)引用當(dāng)前對(duì)象本身,一般來(lái)說(shuō)訪問(wèn)類(lèi)成員時(shí)無(wú)需使用 this ,比如實(shí)現(xiàn)一個(gè) lessThan 方法,下面兩個(gè)實(shí)現(xiàn)是等效的。

def lessThan(that:Rational) =
   this.number * that.denom < that.number * this.denom

def lessThan(that:Rational) =
   number * that.denom < that.number * denom

但如果需要引用對(duì)象自身,this 就無(wú)法省略,比如下面實(shí)現(xiàn)一個(gè)返回兩個(gè) Rational 中比較大的一個(gè)值的一個(gè)實(shí)現(xiàn):

def max(that:Rational) =
      if(lessThan(that)) that else this

其中的 this 就無(wú)法省略。

輔助構(gòu)造函數(shù)

在定義類(lèi)時(shí),很多時(shí)候需要定義多個(gè)構(gòu)造函數(shù),在 Scala 中,除主構(gòu)造函數(shù)之外的構(gòu)造函數(shù)都稱(chēng)為輔助構(gòu)造函數(shù)(或是從構(gòu)造函數(shù)),比如對(duì)于 Rational 類(lèi)來(lái)說(shuō),如果定義一個(gè)整數(shù),就沒(méi)有必要指明分母,此時(shí)只要整數(shù)本身就可以定義這個(gè)有理數(shù)。我們可以為 Rational 定義一個(gè)輔助構(gòu)造函數(shù),Scala 定義輔助構(gòu)造函數(shù)使用 this(…)的語(yǔ)法,所有輔助構(gòu)造函數(shù)名稱(chēng)為 this。

def this(n:Int) = this(n,1)

所有 Scala 的輔助構(gòu)造函數(shù)的第一個(gè)語(yǔ)句都為調(diào)用其它構(gòu)造函數(shù),也就是 this(…),被調(diào)用的構(gòu)造函數(shù)可以是主構(gòu)造函數(shù)或是其它構(gòu)造函數(shù)(最終會(huì)調(diào)用主構(gòu)造函數(shù)),這樣使得每個(gè)構(gòu)造函數(shù)最終都會(huì)調(diào)用主構(gòu)造函數(shù),從而使得主構(gòu)造函數(shù)稱(chēng)為創(chuàng)建類(lèi)單一入口點(diǎn)。在 Scala 中也只有主構(gòu)造函數(shù)才能調(diào)用基類(lèi)的構(gòu)造函數(shù),這種限制有它的優(yōu)點(diǎn),使得 Scala 構(gòu)造函數(shù)更加簡(jiǎn)潔和提高一致性。

私有成員變量和方法

Scala 類(lèi)定義私有成員的方法也是使用 private 修飾符,為了實(shí)現(xiàn) Rational 的規(guī)范化顯示,我們需要使用一個(gè)求分子和分母的最大公倍數(shù)的私有方法 gcd。同時(shí)我們使用一個(gè)私有變量 g 來(lái)保存最大公倍數(shù),修改 Rational 的定義:

scala> class Rational (n:Int, d:Int) {
     |    require(d!=0)
     |    private val g =gcd (n.abs,d.abs) 
     |    val number =n/g 
     |    val denom =d/g 
     |    override def toString = number + "/" +denom
     |    def add(that:Rational)  = 
     |      new Rational( 
     |        number * that.denom + that.number* denom,
     |        denom * that.denom 
     |      ) 
     |    def this(n:Int) = this(n,1) 
     |    private def gcd(a:Int,b:Int):Int =
     |      if(b==0) a else gcd(b, a % b)
     | }
defined class Rational
scala> new Rational ( 66,42)
res0: Rational = 11/7

注意 gcd 的定義,因?yàn)樗莻€(gè)回溯函數(shù),必須定義返回值類(lèi)型。Scala 會(huì)根據(jù)成員變量出現(xiàn)的順序依次初始化它們,因此g必須出現(xiàn)在 number 和 denom 之前。