4

Java 1.6.0_21では、以下の最初の例は正常にコンパイルされます。これは、パラメーター型の境界がむき出しになっているためだと思います。つまり、以下にバインドされている「Z extends Zen」では、Javaにより、Zenは生の非ジェネリック型(ランタイムの「消去された」型に相当)の名前としてスライドできます。これは間違っていて悪いことかもしれませんが、バスに乗って家に帰るのに役立つか、少なくとも奇抜な楽しい時間になることもあります。

public class CorefTest {

    public static interface Tao<Z extends Zen> {
    }

    public static interface Zen<T extends Tao> {
    }
}

Scala 2.8.0.finalでは、以下はCleanOceanWithFishを介して優れたコンパイルを行い、いくつかの基本的な型パラメーターのフックアップを示しています。しかし、ZenとTaoが相互に依存するジェネリック型になると、Scalaコンパイラーは私のウィービング構造を拒否します。コメントのコンパイラエラーを参照してください。

package heaven.piece
class Lucky {
    trait Water {}
    trait CleanWater extends Water {}
    trait Sea [W <: Water] {}
    trait Fish[S <: Sea[CleanWater]] {}

    trait CleanOceanWithFish[F <: Fish[CleanOceanWithFish[F]]] 
                   extends Sea[CleanWater]{}

// Above code compiles fine, but the type constructor pair below doesn't compile 

    trait Tao[Z <: Zen[Tao[Z]]]{};

    trait Zen[T <: Tao[Zen[T]]]{};
}
// error: type arguments [Lucky.this.Tao[Z]] do not conform to trait Zen's 
//     type parameter bounds [T <: Lucky.this.Tao[Lucky.this.Zen[T]]]

// error: type arguments [Lucky.this.Zen[T]] do not conform to trait Tao's 
//     type parameter bounds [Z <: Lucky.this.Zen[Lucky.this.Tao[Z]]]

では、どうすればScala(2.8.0)の結び目をTaoとZenの間で適切に結ぶことができますか?

これは確かに不自然な例ですが、私が本当に望んでいるのは、Scalaを使用して、上記の形式で作業している実際のJavaタイプを拡張することです(これまでのところ、「forSome」と「[_]」を介した既存のタイプは役に立ちません) )。ZenとTaoをScalaでコンパイルすることで、おそらくそのJava拡張機能への道が示されると思います。答えの中でJava拡張機能の問題を検討できるのであれば、はるかに優れています。助けてくれてありがとう!

NikitaS.とKrisN.からの以下の非常に役立つ最初の2つの回答の後に投稿された更新。

さまざまなJava+Scala共参照シナリオについて経験的に学びました。結果として、JavaとScalaの両方で相互運用可能なコアフェレント型が必要な場合、このJava構造は次のようになります。

public static interface JavaFunTao<JFZ extends JavaFunZen<? extends JavaFunTao<JFZ>>> {
    public JFZ consider(JFZ someZen, JavaFunTao<JFZ> otherTao);
}
public static interface JavaFunZen<JFT extends JavaFunTao<? extends JavaFunZen<JFT>>> { 
    public JFT meditate(JFT someTao, JavaFunZen<JFT> otherZen);
}

一番上の最初のJavaの例よりも具体的なタイピングを提供し(生のタイプを回避)、Scalaでは次のように適切に拡張できます。

class HiFunTao[HFZ <: HiFunZen[  _ <: HiFunTao [HFZ]]] extends JavaFunTao[ HFZ] {
    override def consider(someZen: HFZ, otherTao: JavaFunTao[HFZ]) : HFZ = {
        println (this.toString() + " is considering " + someZen + " and " + otherTao);
        someZen
    }
}
class HiFunZen[HFT <: HiFunTao[ _ <:  HiFunZen [HFT]]] extends JavaFunZen[ HFT] {
    override def meditate(someTao: HFT, otherZen: JavaFunZen[HFT]) : HFT = {
        println (this.toString() + " is meditating on " + someTao + " and " + otherZen);
        someTao
    }
}

これらに基づいて単純な具象型を作成し、それらをインスタンス化し、それらのメソッドを呼び出すことができることを確認しました。JavaとScalaの両方で重要なステップは、型パラメーターツリーが現在の宣言型にループバックするポイントに境界付きワイルドカードを配置することです。つまり、Javaでは「?extends」、Scalaでは「_ <:」です。

4

2 に答える 2

3

ZenもTaoも共変ではないため、ZenとTaoには代替可能性の問題があります。これは2.8.1の下で私にとってうまくコンパイルされます:

trait Tao[+Z <: Zen[Tao[Z]]]

trait Zen[+T <: Tao[Zen[T]]]

もちろん、ZまたはTについて瞑想したい場合は、これもうまくいきません。少なくとも、共変型パラメーターが反変の位置にあるという問題があるため、正確には述べられていません。あなたはこのようにその問題を回避することができます:

trait Tao[+Z <: Zen[Tao[Z]]] {
  def meditate[M >: Z](m: M) = ()
}

trait Zen[+T <: Tao[Zen[T]]] {
  def meditate[M >: T](m: M) = ()
}

ただし、これにより、実装に望ましくない制約が生じる可能性があります。少なくとも、混乱を招きます。:)

アップデート:

ちなみに、これはNSkvortsovの回答の更新で言及された問題を回避します。これはうまくコンパイルされます:

class Zazen extends Zen[Tao[Zazen]]
于 2011-04-07T15:14:38.723 に答える
2

私は、これがあなたが必要とするものだと思います:

class MyClass {

  trait Tao[Z <: Zen[_]]{};
  trait Zen[T <: Tao[_]]{};

}

このスニペットはScala2.8.1によって正常にコンパイルされました

アップデート

残念ながら、拡張CorefTest.ZenCorefTest.Taoてscalaで実行することは不可能です。これが理由です。

Javaでインターフェースを実装する唯一の方法は、 raw型を使用することです。

public class TaoImpl<Z extends CorefTest.Zen> implements CorefTest.Tao<Z> { }

public class ZenImpl<T extends CorefTest.Tao> implements CorefTest.Zen<T> { }

次のようなクラスをインスタンス化できます。

TaoImpl<ZenImpl> tao = new TaoImpl<ZenImpl>();
ZenImpl<TaoImpl> zen = new ZenImpl<TaoImpl>();

しかし、scala はraw型をサポートしていません。したがってTaoImplZenImpl定義することはできません。詳細については、この電子メールスレッドと問題#2091および#1737を参照してください。

于 2011-04-07T11:40:07.003 に答える