第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

如何覆蓋案例類同伴中的應(yīng)用

如何覆蓋案例類同伴中的應(yīng)用

這就是這種情況。我想這樣定義一個(gè)案例類:case class A(val s: String)并且我想定義一個(gè)對(duì)象以確保在創(chuàng)建類的實(shí)例時(shí),“ s”的值始終為大寫,如下所示:object A {  def apply(s: String) = new A(s.toUpperCase)}但是,這不起作用,因?yàn)镾cala抱怨apply(s:String)方法定義了兩次。我知道case類語法會(huì)自動(dòng)為我定義它,但是我是否還有其他方法可以實(shí)現(xiàn)此目的?我想堅(jiān)持使用case類,因?yàn)槲蚁雽⑵溆糜谀J狡ヅ洹?
查看完整描述

2 回答

?
浮云間

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超4個(gè)贊

發(fā)生沖突的原因是案例類提供了完全相同的apply()方法(相同的簽名)。


首先,我建議您使用require:


case class A(s: String) {

  require(! s.toCharArray.exists( _.isLower ), "Bad string: "+ s)

}

如果用戶嘗試創(chuàng)建s包含小寫字符的實(shí)例,則將引發(fā)Exception。這是用例類的一種很好的用法,因?yàn)槭褂媚J狡ヅ洌╩atch)時(shí),您在構(gòu)造函數(shù)中輸入的內(nèi)容也同樣如此。


如果這不是您想要的,那么我將創(chuàng)建構(gòu)造函數(shù)private并強(qiáng)制用戶僅使用apply方法:


class A private (val s: String) {

}


object A {

  def apply(s: String): A = new A(s.toUpperCase)

}

如您所見,A不再是case class。我不確定具有不可變字段的case類是否用于修改傳入的值,因?yàn)槊Q“ case class”表示應(yīng)該可以使用提?。ㄎ葱薷牡模?gòu)造函數(shù)參數(shù)match。


查看完整回答
反對(duì) 回復(fù) 2019-11-12
?
慕尼黑8549860

TA貢獻(xiàn)1818條經(jīng)驗(yàn) 獲得超11個(gè)贊

盡管我在下面編寫的答案仍然足夠,但值得一提的是與案例類的伴隨對(duì)象相關(guān)的另一個(gè)答案。即,如何精確地重現(xiàn)編譯器生成的隱式伴隨對(duì)象,該對(duì)象僅在定義案例類本身時(shí)發(fā)生。對(duì)我來說,事實(shí)證明這與直覺相反。


摘要:

您可以更改案例類參數(shù)的值,然后再將其存儲(chǔ)在案例類中,非常簡(jiǎn)單,同時(shí)仍保留有效的(已指定)ADT(抽象數(shù)據(jù)類型)。盡管解決方案相對(duì)簡(jiǎn)單,但是發(fā)現(xiàn)細(xì)節(jié)卻更具挑戰(zhàn)性。


詳細(xì)信息:

如果要確保只能實(shí)例化case類的有效實(shí)例,這是ADT(抽象數(shù)據(jù)類型)背后的基本假設(shè),則必須執(zhí)行許多操作。


例如,copy默認(rèn)情況下,案例類提供了編譯器生成的方法。因此,即使您非常小心以確保僅通過顯式伴隨對(duì)象的apply方法創(chuàng)建了僅能包含大寫值的實(shí)例,以下代碼仍將生成具有小寫值的case類實(shí)例:


val a1 = A("Hi There") //contains "HI THERE"

val a2 = a1.copy(s = "gotcha") //contains "gotcha"

此外,案例類還實(shí)現(xiàn)了java.io.Serializable。這意味著可以通過簡(jiǎn)單的文本編輯器和反序列化來顛覆只包含大寫實(shí)例的謹(jǐn)慎策略。


因此,對(duì)于使用案例類的各種方式(善意和/或惡意),您必須采取以下措施:


對(duì)于您的顯式伴侶對(duì)象:

使用與案例類完全相同的名稱創(chuàng)建它

可以訪問案例類的私有部分

創(chuàng)建一個(gè)apply與您的case類的主構(gòu)造函數(shù)具有完全相同的簽名的方法

一旦完成步驟2.1,它將成功編譯

提供一個(gè)使用new運(yùn)算符獲取案例類實(shí)例的實(shí)現(xiàn),并提供一個(gè)空的實(shí)現(xiàn){}

現(xiàn)在,這將嚴(yán)格按照您的條件實(shí)例化案例類

{}由于聲明了案例類,因此必須提供空實(shí)現(xiàn)abstract(請(qǐng)參閱步驟2.1)。

對(duì)于您的案例類:

聲明它 abstract

防止Scala編譯器apply在伴隨對(duì)象中生成方法,而該方法正是導(dǎo)致“方法被定義兩次...”的編譯錯(cuò)誤(上面的步驟1.2)

將主要構(gòu)造函數(shù)標(biāo)記為 private[A]

現(xiàn)在,主要構(gòu)造函數(shù)僅可用于case類本身及其伴隨對(duì)象(我們?cè)谏厦娴牟襟E1.1中定義的對(duì)象)

創(chuàng)建一個(gè)readResolve方法

提供一個(gè)使用apply方法的實(shí)現(xiàn)(上面的步驟1.2)

創(chuàng)建一個(gè)copy方法

定義它與案例類的主要構(gòu)造函數(shù)具有完全相同的簽名

對(duì)于每一個(gè)參數(shù),使用相同的參數(shù)名稱添加的默認(rèn)值(例如:s: String = s)

提供一個(gè)使用apply方法的實(shí)現(xiàn)(下面的步驟1.2)

這是通過上述操作修改的代碼:


object A {

  def apply(s: String, i: Int): A =

    new A(s.toUpperCase, i) {} //abstract class implementation intentionally empty

}

abstract case class A private[A] (s: String, i: Int) {

  private def readResolve(): Object = //to ensure validation and possible singleton-ness, must override readResolve to use explicit companion object apply method

    A.apply(s, i)

  def copy(s: String = s, i: Int = i): A =

    A.apply(s, i)

}

這是實(shí)現(xiàn)require(在@ollekullberg答案中建議)并確定放置任何類型的緩存的理想位置后的代碼:


object A {

  def apply(s: String, i: Int): A = {

    require(s.forall(_.isUpper), s"Bad String: $s")

    //TODO: Insert normal instance caching mechanism here

    new A(s, i) {} //abstract class implementation intentionally empty

  }

}

abstract case class A private[A] (s: String, i: Int) {

  private def readResolve(): Object = //to ensure validation and possible singleton-ness, must override readResolve to use explicit companion object apply method

    A.apply(s, i)

  def copy(s: String = s, i: Int = i): A =

    A.apply(s, i)

}

如果通過Java interop使用此代碼,則此版本將更安全/更可靠(將case類隱藏為實(shí)現(xiàn),并創(chuàng)建一個(gè)防止派生的最終類):


object A {

  private[A] abstract case class AImpl private[A] (s: String, i: Int)

  def apply(s: String, i: Int): A = {

    require(s.forall(_.isUpper), s"Bad String: $s")

    //TODO: Insert normal instance caching mechanism here

    new A(s, i)

  }

}

final class A private[A] (s: String, i: Int) extends A.AImpl(s, i) {

  private def readResolve(): Object = //to ensure validation and possible singleton-ness, must override readResolve to use explicit companion object apply method

    A.apply(s, i)

  def copy(s: String = s, i: Int = i): A =

    A.apply(s, i)

}

盡管這直接回答了您的問題,但是還有更多的方法可以在實(shí)例緩存之外擴(kuò)展案例類的途徑。為了滿足我自己的項(xiàng)目需求,我創(chuàng)建了一個(gè)更擴(kuò)展的解決方案,該解決方案已在CodeReview(StackOverflow姐妹網(wǎng)站)上進(jìn)行了記錄。如果您最終查看,使用或利用我的解決方案,請(qǐng)考慮給我留下反饋,建議或問題,并在合理的范圍內(nèi),我將盡力在一天之內(nèi)做出答復(fù)。


查看完整回答
反對(duì) 回復(fù) 2019-11-12
?
慕桂英3389331

TA貢獻(xiàn)2036條經(jīng)驗(yàn) 獲得超8個(gè)贊

我不知道如何apply在伴隨對(duì)象中重寫該方法(如果可能的話),但是您也可以對(duì)大寫字符串使用特殊類型:


class UpperCaseString(s: String) extends Proxy {

  val self: String = s.toUpperCase

}


implicit def stringToUpperCaseString(s: String) = new UpperCaseString(s)

implicit def upperCaseStringToString(s: UpperCaseString) = s.self


case class A(val s: UpperCaseString)


println(A("hello"))

上面的代碼輸出:


A(HELLO)

您還應(yīng)該看看這個(gè)問題及其答案:Scala:是否可以覆蓋默認(rèn)的case類構(gòu)造函數(shù)?


查看完整回答
反對(duì) 回復(fù) 2019-11-12
  • 2 回答
  • 0 關(guān)注
  • 505 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)