2015-07-13 12 views
13

Yansıtılan bir türle bir bağımsız değişken kabul eden bir işleve bir nesne iletmek ve nesnenin türünün onu çevreleyen nesneden geldiğini anlamak için Scala'yı almak istiyorum. İşte zorluk göstermek için bazı basit kod:Scala neden açık öz referanstan bile olsa yola bağımlı türün yolunu öğrenemiyor?

trait Cult { cult_ => 
    case class CultLeader(personality: Personality) { 
    val cult = cult_ 
    val follower = personality.attractFollower(this) 
    } 
    case class Follower(leader: CultLeader, name: String) 
} 

trait Personality { 
    def attractFollower(leader: Cult#CultLeader) = 
    leader.cult.Follower(leader, "Fred") <-- THIS LINE FAILS TO COMPILE 
} 

Başka bir deyişle, bir CultLeader en Kişilik CultLeader aynı Cult takipçisi çekmek gerekir. Bu derler ve böyle bir döküm eklerseniz çalıştırır doğru

TypeProjection.scala:11: error: type mismatch; 
found : Cult#CultLeader 
required: leader.cult.CultLeader 
    leader.cult.Follower(leader, "Fred") 
         ^

:

Scala 2.11.2 derleyici diyor hantal görünüyor

leader.cult.Follower(leader.asInstanceOf[leader.cult.CultLeader], "Fred") 

ve kontrol çalışma zamanı tanıtır derleme zamanında çıkarılabilir olması gereken bir şey için. En azından bir çözümüm var. Scala derleyicisini leader 'türünün aslında leader.cult.CultLeader olduğu sonucunu çıkarmak için nasıl alabilirim?

cult'u başka bir argüman olarak attractFollower'a geçirmemeyi tercih ederim. Gerçek kodumda bu, cult parametresinin çok fazla çirkin olmasına neden olabilir - gerçekten hiç iletilmemesi gerektiğinde.

cevap

9

basit bir yoludur: Burada

trait Cult { cult_ => 
    case class CultLeader(personality: Personality) { 
    val cult = cult_ 
    val follower = personality.attractFollower(this) 
    } 
    case class Follower(leader: Cult#CultLeader, name: String) // <-- Cult#CultLeader here 
} 

trait Personality { 
    def attractFollower(leader: Cult#CultLeader) = 
    leader.cult.Follower(leader, "Fred") 
} 

// Exiting paste mode, now interpreting. 

defined trait Cult 
defined trait Personality 

açıkça Follower aslında asInstanceOf ile zorlamaya çalışıyoruz herhangi projeksiyon, alabilir belirterek ediyoruz.

trait Cult { 
    case class CultLeader(personality: Personality) { 
    def fl(name: String) = Follower(this, name) 
    val follower = personality.attractFollower(this) 
    } 
    case class Follower(leader: CultLeader, name: String) 
} 

trait Personality { 
    def attractFollower(leader: Cult#CultLeader) = leader.fl("Fred") 
} 

veya

trait Cult { 
    case class CultLeader(personality: Personality) { ld => 
    val follower = personality.attractFollower(this) 
    case class Follower(name: String) { val leader = ld } 
    } 
} 

trait Personality { 
    def attractFollower(leader: Cult#CultLeader) = leader.Follower("Fred") 
} 

GÜNCELLEME: örnek daha net neden Scala o ne yaptığını yapabilir yapmanın başka bir yolu yoktur


yapıyor:

trait Cult { cult_ => 
    case class CultLeader(personality: Personality) { 
    val cult: Cult = cult_ //could be new Cult{} as well 
    val l = this.asInstanceOf[cult.CultLeader] //We have to do asInstanceOf here because Scala have no glue (from type signature) that this cult is same as cult_ 
    val follower = personality.attractFollower(this) 
    } 

    case class Follower(leader: CultLeader, name: String) 
} 

trait Personality { 
    def attractFollower(leader: Cult#CultLeader) = 
    leader.cult.Follower(leader.l, "Fred") 
} 

// Exiting paste mode, now interpreting. 
defined trait Cult 
defined trait Personality 

Ve burada doğru bir şekilde istediğimizi yapar hangi son çözümdür: Burada

trait Cult { cult_ => 
    case class CultLeader(personality: Personality) { 
    val cult: cult_.type = cult_ 
    val l: cult.CultLeader = this 
    val follower = personality.attractFollower(this) 
    } 

    case class Follower(leader: CultLeader, name: String) 

} 

trait Personality { 
    def attractFollower(leader: Cult#CultLeader) = 
    leader.cult.Follower(leader.l, "Fred") 
} 

// Exiting paste mode, now interpreting. 
defined trait Cult 
defined trait Personality 

yakalamak cult_.type yolu bağımlı (öngörülen) olmasıdır.

+0

Follower'ın "lideri" ile aynı Cult'tan olmasını gerektiren bir yol var mı? –

+0

Evet, bu sizin somut çözümünüzdü - ancak ** beton ** kült bir lider gerektiren bir ** kült bir ** kült bir lider geçemezsiniz - derleme zamanında kontrol etmek için hiçbir yolu yoktur Scala, 'çekicinin' ne demek istediğini tam olarak bilmiyor (yapı modülü dışında bir kod olabilir). Yani, fonksiyonunuz Int Int' gerektirirken, çözümün anlamı "Any" gibi. Bu nedenle, somut kült projeksiyon gerektirip, herhangi bir projeksiyonu eşzamanlı olarak geçirmenin bir yolu yoktur - bu mantıksal olarak yanlıştır. – dk14

+0

Çekicinin her yerden çağrılması mümkün olsa da, "Çekiciyi" çeken liderle aynı Kültünün İzleyicisini yaratamamalı mıydı? –

İlgili konular