2016-08-23 4 views
2

`は` copy`を定義し、私はもっとうまくできると思った、しかしが考えるtrait`

def copy(x: X, newValue: String): X = x match { 
    case A(_) => A(newValue) 
    case B(_) => B(newValue) 
} 

、すなわち正確に。 BXのサブクラスであるため

ため、技術的に、Aが入力されたという理由だけで、Bを出力することができました。

<console>:17: error: type mismatch; 
found : A 
required: T 
      case A(_) => A(newValue) 
         ^
<console>:18: error: type mismatch; 
found : B 
required: T 
      case B(_) => B(newValue) 
         ^

どのように私は与えられた署名付きcopyBetterを実装することができます:私は、コンパイル時エラーを得た、

def copyBetter[T <: X](x: T, newValue: String): T = x match { 
case A(_) => A(newValue) 
case B(_) => B(newValue) 
} 

しかし:

は、だから私は試しましたか?

+0

私は同様の問題があったと思いますが、Xを返すように解決しました。ここで問題となるのは、戻り値の型が動的で、呼び出す前にどの型が 'T 'なのかわからないということです。一般的なメソッドへの通常の呼び出しから、その場合は返すことが分かっているので、事前に型を指定することができます。ここではできません。 –

+0

私は、あなたの問題がそれに対応するかどうかを確かめるために、形のないものを見ていきます。 – Reactormonk

答えて

1

唯一の方法は、このシグネチャを持つメソッドを実装する(nullを無視して)def copyBetter[T <: X](x: T, newValue: String): T = xです!どうして?シングルトンタイプが存在するためです。

val x = A(1) 
val y: x.type = copyBetter[x.type](x, 2) 

yのタイプはyx(又はnull)と同じオブジェクトでなければならないことを述べている:。x.typeXのサブタイプであるので、この署名が与えられると、以下は、コンパイルする必要がありますあなたの実装ではそうではないので、この実装は署名に適合しません。

+0

'シングルトンタイプが存在するので'あなたはもっと言いたいことやリンクを教えてくれませんか? 「シングルトンタイプ」とは何ですか? –

+0

この例の 'x.type'はシングルトンタイプです。これはちょうど2つの値を持つ型です: 'x'と' null'です。 –

1

私は次のことをお勧め:

def copyBetter[T <: X](x: T, newValue: String): X = x match { 
    case A(_) => A(newValue) 
    case B(_) => B(newValue) 
} 
+0

この例では、 'copyBetter'は' A'を受け入れることができますが、 'B'を返します。定義は合理的ではないが、私はそれがコンパイルされると主張するだろう。 1つ上のレベルを上げる方法はありません。つまり、 'X 'の入力子とその出力と同じ型を必要としますか? –

+0

コンパイラは、実行時に 'x 'がどのケースで一致するかを知ることができないので、最も特定のスーパータイプを選択します。これは' X'です。私はそこに道があるとは思わない。 –

+1

実際にコンパイルできますか? '_ <:X 'は型自体ではなく、_argument_(例えば' List [_ <:X] ')の型としてのみ許されます。私は "Unbound wildcard type"を取得します:http://scastie.org/21879。 –

1

あなたはTが、Xを返されていません。 AおよびBXですが、Tは含まれていません。

この署名を使用して試してみてください:

def copyBetter[T <: X](x: T, newValue: String): X = // ... 
+0

この有益な答えをありがとう。彼は1分早く答えたので、私はゾルタンを受け入れた。 –

+1

ゾルタンの答えと同じです:元の 'コピー'の代わりにこれを使うことは絶対にありません。 –

+0

引数の型が 'X'のところで' X'の子を常に渡すことができるので利点はありませんか?言い換えれば、制約は単に 'x:X'と書く以外の何かを追加するものではありませんか? –

0

シンプル - どのようにそれは、メソッド本体内にも関与していないときに、戻り値の型はTことを期待しています。 Tは無関係で、返されるタイプはABという共通の祖先です。

また、あなたのようにそれを定義すべきではありません。

def copy(newValue: String): X = this match { 
    case _: A => A(newValue) 
    case _: B => B(newValue) 
}