2012-01-23 42 views
1

私は解決できないような型の不一致の原因となっているシナリオがあります。スカラ型の不一致エラー

abstract class Msg 

trait Channel[M <: Msg] { 
    def receive(): M 
    def ack(envelope: M) 
} 

object ChannelSender { 
    private var channel : Channel[_ <: Msg] = _ 
    def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel 

    def test() { 
    val msg = channel.receive() 
    channel.ack(msg) // Type mismatch here 
    } 
} 

コンパイラからのエラーは次のとおりです:ここでは、コードの簡易版です

型の不一致。見つかった:(基になる型 com.msgtest.Envelope付き)msg.typeが必要:_ $ 1ここで、タイプ_ $ 1 <: com.msgtest.Envelope

私はこの作業を取得するために作ることができるの変更のどのような

?また、変更はその次具体的な実装のコンパイルが必要になります。

class SomeMsg extends Msg 

object SomeChannel extends Channel[SomeMsg] { 
    def receive(): SomeMsg = { null.asInstanceOf[SomeMsg] } 
    def ack(envelope: SomeMsg) {} 
} 

object Setup { 
    ChannelSender.assignChannel(SomeChannel) 
} 

答えて

4

私はそれを2回交換してScalaの2.9の下でコンパイルするために得ることができ、最初の変更は不変値val c = channelを使用することです

trait Channel[M <: Msg] { 
    type M2 = M  // Introduce a type member that's externally visible 
    def receive(): M2 
    def ack(envelope: M2) 
} 

object ChannelSender { 
    private var channel : Channel[_ <: Msg] = _ 
    def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel 

    def test() { 
    val c = channel // An immutable value, so that c.M2 is stable 
    val msg = c.receive() 
    c.ack(msg)  // OK now 
    } 
} 

、その結果、パスに依存するタイプc.M2は常に同じことを意味します。第2の変更は、型のメンバtype M2 = Mを特性Channelに導入することです。私はこれがなぜ必要なのか完全にはわかっていません(バグかもしれません)。注目すべきことの1つは、c.M2が有効なタイプであるのに対し、c.Mは未定義です。

+0

良いこと、ありがとう!私はなぜこれらの変更のいずれかが必要だった理由は分かりません。 Channel.Mが外部から見えない場合は、それは何ですか?特性/クラスの外で使用できるように型パラメータの型エイリアスを作成する必要がありますか? ChannelSenderを変更すると、同じ 'channel'オブジェクトで' receive() 'と' ack'を呼び出すので、パス依存型c.M2は同じことを意味しませんか? – Josh

+0

素晴らしい質問。最初のものについては、私は答えを知らない。たぶん、メーリングリストの知識が豊富な人が役に立つかもしれません。 2つ目は、この場合、 'channel'オブジェクトが変更されていないことをScalaが知ることができたことに同意しますが、一般的には、' var'が同じままであることを仮定していると仮定します。 –

関連する問題