How do two related constructors of type w60> type refer to each other as type parameters?

In Java 1.6.0_21, the first example below compiles fine, and I think that since parameter type restrictions are bare. That is, in the β€œZ extends Zen” section below, Java resolves Zen for the slide as the name of a raw, non-generic type (the equivalent of the runtime is β€œerased”, type). It may be wrong and bad, but it can also be useful or at least stupid good times on a bus home:

public class CorefTest { public static interface Tao<Z extends Zen> { } public static interface Zen<T extends Tao> { } } 

In Scala 2.8.0.final, below is compiled through CleanOceanWithFish, showing some basic types of param connections. But when we get to Zen and Tao, being common types interdependent, the Scala compiler rejects my weaving structure. See compiler errors in the comments.

 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 // type parameter bounds [T <: Lucky.this.Tao[Lucky.this.Zen[T]]] // error: type arguments [Lucky.this.Zen[T]] do not conform to trait Tao // type parameter bounds [Z <: Lucky.this.Zen[Lucky.this.Tao[Z]]] 

So, how can I properly bind the Scala node (2.8.0) between Tao and Zen?

This is certainly a contrived example, but I really want to use Scala to extend some real Java types that I work in the above form (which existential types through "forSome" and "[_]" don't help me yet. I think getting Zen and Tao compilation in Scala is likely to show the way to this Java extension. If you can consider the Java extension problem in your answer, so much the better. Thanks for any help!

Update , published after the very useful first two answers below from Nikita S. and Chris N.

I have empirically learned about various Java + Scala scripting scenarios. The result is that when we want to have compatible coreferent types in both Java and Scala, then this Java construct:

 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); } 

provides a more specific typification than my first Java example at the top (avoiding raw types), and then extends correctly in Scala as follows:

 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 } } 

I checked that we can create simple concrete types based on them, create them and refer to their methods. The key step in Java and Scala is to place a restricted template at the point where the type parameter tree returns to the current declaration type, that is, "? Extends" in java and "_ <:" in Scala.

+4
source share
2 answers

Since neither Zen nor Tao is covariant, there is a problem with interchangeability in your Zen and Tao. This compiles for me in 2.8.1:

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

Of course, if you want to meditate on Z or T, this also will not work for you, at least not as indicated due to a problem with the covariant type parameter in a contravariant position. You can work around this problem as follows:

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

but it can still create restrictions for your implementation that you might not want. This is confusing, at least. :)

Update:

This also, by the way, avoids the problem mentioned in updating NSkvortsov's answer. This compiles fine:

 class Zazen extends Zen[Tao[Zazen]] 
+3
source

I think this is what you need:

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

This snippet was successfully compiled by Scala 2.8.1

Update

Unfortunately, the extension of CorefTest.Zen and CorefTest.Tao in Scala is not possible. That's why.

The only way to implement interfaces in java is to use raw types:

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

how to create such classes:

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

But scala does not support raw types. Therefore, TaoImpl and ZenImpl simply impossible to determine. See This Email Flow and Issues # 2091 and # 1737 for a detailed discussion.

+2
source

Source: https://habr.com/ru/post/1347086/


All Articles