簡體   English   中英

Scala在不可變對象上為“setter”命名約定

[英]Scala naming convention for “setters” on immutable objects

我不知道在不可變對象上叫什么叫“setter”?

對於一個可變對象Person,setter的工作方式如下:

class Person(private var _name: String) {
  def name = "Mr " + _name
  def name_=(newName: String) {
    _name = newName
  }
}

val p = new Person("Olle")
println("Hi "+ p.name)
p.name = "Pelle"
println("Hi "+ p.name)

這一切都很好,但如果Person是不可變的呢?

class Person(private val _name: String) {
  def name = "Mr " + _name
  def whatHereName(newName: String): Person = new Person(newName)
}

val p = new Person("Olle")
println("Hi "+ p.name)
val p2 = p.whatHereName("Pelle")
println("Hi "+ p2.name)

我應該whatHereName叫?

編輯:我需要把東西放在“setter”方法中,如下所示:

class Person(private val _name: String) {
  def name = "Mr " + _name
  def whatHereName(newName: String): Person = {
    if(name.length > 3)
      new Person(newName.capitalize)
    else
      throw new Exception("Invalid new name")
  }
}

真正的代碼比這大得多,所以對copy方法的簡單調用是行不通的。

編輯2:

由於我的偽造例子有很多評論(這是不正確的)我最好給你鏈接到真正的類( Avatar )。

我不知道該叫什么的“setter”方法是updateStrengthupdateWisdom ......但是我很快就會把它withStrength ..

我喜歡jodatime的方式。 這將是withName。

val p = new Person("Olle")
val p2 = p.withName("kalle");

更多jodatime示例: http ://joda-time.sourceforge.net/

for this purpose. 為此,Scala案例類具有自動生成的方法 它的使用方式如下:


val p2 = p.copy(name = "Pelle")

如果在“修改”字段時需要執行驗證等,那么為什么在首次創建對象時這與驗證有什么不同呢?

在這種情況下,您可以將必要的驗證/錯誤拋出邏輯放在案例類的構造函數中,只要通過copy方法創建新實例,就會使用此邏輯。

您可以為此定義一個方法。 無論是copy ,或在情況下,它已經是一個案例類, with

class Person(private val _name: String) {
  def name = "Mr " + _name
  def copy(name: String = _name): Person = new Person(name)
}

編輯

鏈接示例上的copy方法應如下所示:

// Setters
def copy(strength: Int = features.strength,
         wisdom: Int = features.wisdom,
         charisma: Int = features.charisma,
         hitpoints: Int = features.hitpoints): Avatar = {
  if (hitpoints != features.hitpoints)
    println("setHitpoints() old value: " + features.hitpoints + ", new value: " + hitpoints)

  if (hitpoints > 0) 
    updateCreatureFeature(
      features.copy(strength = strength,
                    wisdom = wisdom,
                    charisma = charisma,
                    hitpoints = hitpoints))
  else
    throw new DeathException(name + " died!")

  // Alternate coding (depend on thrown exception on "check"):
  // check(strength, wisdom, charisma, hitpoints)
  // updateCreateFeature(...)
}

添加到Oleg的答案,你會寫這樣的類:

case class Person(name: String) //That's all!

你會像這樣使用它:

val p = Person("Olle") // No "new" necessary
println("Hi" + p.name)
val p2 = p.copy(name="Pelle")
println("Hi" + p2.name)    

使用上面的復制方法是可能的,但在你的簡單情況下我會使用:

val p2 = Person("Pelle")

如果你有類似的類,復制方法顯示了它們的優勢:

case class Person(name: String, age: Int, email: EMail, pets: List[Pet] = List())
val joe = Person("Joe", 41, EMail("joe@example.com"))
val joeAfterHisNextBirthday = joe.copy(age=42)

至於現在,我對不可變對象的所有“setter”類方法使用update<Field>名稱約定。

我不能使用set<Field>因為它提醒了Java中的可變setter。

對於返回與當前實例具有相同標識的新實例的所有方法,您如何使用update<Field>

雖然以前的答案解決了這個問題,但我想分享一下我如何處理不可變對象(這只是語法糖)。

為了有一個更清晰的語法(恕我直言),我在不可變類中實現apply方法,在case類中返回copy方法的結果,在它是常規類時返回一個新實例。 即:

import java.util.Date

class Tournament (val name: String, val start: Date) {
  /* With case class
  def apply (name: String = this.name, start: Date = this.start) =
    copy (name, start)
  */

  def apply (name: String = this.name, start: Date = this.start) =
    new Tournament (name, start)

  override def toString () = s"${name} at ${start}"
}

object Main extends App {
  val tour = new Tournament ("Euroleague", new Date)
  val tour2 = tour (name = tour.name + " 2014")
  println (tour)
  println (tour2)
}

這使得“mutator”方法成為該類的任何實例的默認方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM