1. ホーム
  2. scala

[解決済み] ケースクラスのコンパニオンでapplyをオーバーライドする方法

2023-05-31 22:19:11

質問

さて、こんな状況です。 このようなケースクラスを定義したいのです。

case class A(val s: String)

で、このクラスのインスタンスを作るときに、's'の値が常に大文字になるようにオブジェクトを定義したいのですが、こんな感じです。

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

しかし、これはScalaがapply(s: String)メソッドが2回定義されていると文句を言うので、うまくいきません。 caseクラスの構文が自動的に定義してくれることは理解していますが、これを実現する他の方法はないのでしょうか? 私はパターンマッチに使いたいので、caseクラスにこだわりたいのです。

どのように解決するのですか?

衝突の原因は、caseクラスが全く同じapply()メソッド(同じシグネチャ)を提供していることです。

まず最初に、requireを使うことを提案したいと思います。

case class A(s: String) {
  require(! s.toCharArray.exists( _.isLower ), "Bad string: "+ s)
}

これは、ユーザが s に小文字を含むインスタンスを作成しようとした場合に Exception をスローします。これはケースクラスの良い使い方です。コンストラクタに入力した内容は、パターンマッチ ( match ).

もし、これがあなたの望むものでないなら、私はコンストラクタを private にして、ユーザには強制的に だけ を強制的に適用させます。

class A private (val s: String) {
}

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

ご覧の通り、Aはもはや case class . というのも、quot;case class" という名前から、コンストラクタの (変更されていない) 引数を抽出するために match .