Choices with def and val in Scala

http://blog.jessitron.com/2012/07/choices-with-def-and-val-in-scala.html

In Scala, one can define class properties with either "def" or "val." Using "def", one can define the property with or without parentheses, and with or without the equal sign. Why is this? What are the consequences?

For illustrative purposes, we'll use a block of code that printing to the console, then returns an int. This shows when the code runs.

carrot.scala:

import System.out._ 
class Carrot { 
   val helloTen = { println "hello"; 10 } 
}

When a val is initialized to a block of code, the code runs at construction, and the property contains 10. The block only runs once. You can see this in the REPL:

scala> :load carrot.scala
...
scala> val c = new Carrot()
hello
c: Carrot = Carrot@5fe2b9d1
scala> c.helloTen
res5: Int = 10

If you change val to def, that block of code instead becomes a method. It prints and returns 10 every time it is accessed.

carrot.scala:
import System.out._ 
class Carrot { 
   def helloTen = { println "hello"; 10 } 
}

Use the REPL to observe that the code runs at every access:

scala> :load carrot.scala
...
scala> val c = new Carrot()
c: Carrot = Carrot@5689a400
scala> c.helloTen
hello
res7: Int = 10
scala> c.helloTen
hello
res8: Int = 10

Now I'm going to stop showing you what the REPL prints out, because that's boring to read. Try it for yourself.

So "def" or "val" determines whether the block of code runs only at construction, or at every access. There's another consequence: in a subclass, you can override a def with a val or a def, but you can only override a val with a val. When Scala has a val, it knows the value of that expression will never change. This is not true with def; therefore declaring something as val says more than declaring a def.

Let's move on with "def" because it's more flexible for extension. Next decision: use parentheses or not? We can choose between
def helloTen = { println "hello"; 10 }
and
def helloTen() = { println "hello"; 10 }

The consequences of this decision are: if you include the parentheses in the definition, then the property can be accessed with or without parentheses. If you do not include parentheses in the definition, then the property must be accessed without parentheses.

Here's a summary of our options:
With () No ()
val n/a runs at construction;
override with val;
access with no ()
def runs at every access;
override with val or def;
access with or without () runs at every access;
override with val or def;
access with no () ?
The idiomatic rule of thumb is: use parentheses if the method changes state; otherwise don't.

Now here's a subtlety. If we use def with or without parentheses, the property can be overridden in a subclass by a def with or without parentheses (or a val without parentheses). This has strange consequences: If I subclass Carrot and override the property, but change whether parentheses follow the property declaration, then the interface of the subclass does not match the superclass.

carrot.scala:
import System.out._
class Carrot { 
    def helloTen = { println ("hello"); 10 }
} 

class Soybean extends Carrot { 
    override def helloTen() = 14 
}

On a Carrot, I can access helloTen only without parentheses. On a Soybean, I can access the property with or without parentheses. If I cast a Soybean to a Carrot, then I can access helloTen only without parentheses. Either way, the Soybean's helloTen property evaluates to 14, as a good polymorphic method should.

Stranger still, reverse it: if Carrot defines helloTen with parentheses and Soybean without, then a Carrot (or a Soybean cast to a Carrot) will helloTen with or without parentheses -- but a Soybean will only helloTen without parentheses! Therefore, a method call that works on the superclass errors on the subclass. Does this sound like a violation of LSP to you? Technically instances of the subclass can be substituted for instances of the superclass, but the interface of the subclass is smaller than that of the superclass. Wah? If this makes sense to you, please comment.

For another method-declaration subtlety, consider the equals sign.

I'm running Scala 2.9.2.

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稠项,一起剝皮案震驚了整個濱河市栗菜,隨后出現(xiàn)的幾起案子坞淮,更是在濱河造成了極大的恐慌缎除,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝴韭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門跑慕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來万皿,“玉大人,你說我怎么就攤上這事核行±喂瑁” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵芝雪,是天一觀的道長减余。 經(jīng)常有香客問我,道長惩系,這世上最難降的妖魔是什么位岔? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任如筛,我火速辦了婚禮,結(jié)果婚禮上抒抬,老公的妹妹穿的比我還像新娘杨刨。我一直安慰自己,他們只是感情好擦剑,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布妖胀。 她就那樣靜靜地躺著,像睡著了一般惠勒。 火紅的嫁衣襯著肌膚如雪赚抡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天纠屋,我揣著相機與錄音涂臣,去河邊找鬼。 笑死售担,一個胖子當著我的面吹牛赁遗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灼舍,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼吼和,長吁一口氣:“原來是場噩夢啊……” “哼涨薪!你這毒婦竟也來了骑素?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤刚夺,失蹤者是張志新(化名)和其女友劉穎献丑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侠姑,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡创橄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了莽红。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妥畏。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖安吁,靈堂內(nèi)的尸體忽然破棺而出醉蚁,到底是詐尸還是另有隱情,我是刑警寧澤鬼店,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布网棍,位于F島的核電站,受9級特大地震影響妇智,放射性物質(zhì)發(fā)生泄漏滥玷。R本人自食惡果不足惜氏身,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惑畴。 院中可真熱鬧蛋欣,春花似錦、人聲如沸如贷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倒得。三九已至泻红,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霞掺,已是汗流浹背谊路。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留菩彬,地道東北人缠劝。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像骗灶,于是被迫代替她去往敵國和親惨恭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的閱讀 13,441評論 5 6
  • k v c pragma mark KVC---key value coding 鍵值編碼 // kv...
    向日葵_wwx閱讀 256評論 0 0
  • 兩個人可以有天差地別的工作但卻總能為對方畫龍點睛一個數(shù)字 一個詞 一撇一捺 或一句話兩個人可以自成自己的世界但偶爾...
    黑洞小姐閱讀 241評論 3 1
  • 摘一朵云來蓋了 把太陽蓋了 如此 花不開了 葉不綠了 燥熱的汗 假裝不流了 扯一片葉子來蒙了 把眼睛蒙了 如此 月...
    蓮籽閱讀 109評論 0 1
  • 01 前天騎著摩拜單車繞了西長安街一圈 回到家的時候咕咚顯示騎車15公里 這應該是我騎自行車第一次用了這么長時間 ...
    小阿姨吖閱讀 533評論 0 2