2014-02-26 61 views
1

Scala类型推理系统有其局限性。如何帮助scala类型推理?

例如在以下类中。我希望有一个工厂FooFactory,它可以创建FooFooChanger的实例,它们可以修改由FooFactory创建的实例。

创建后我Foo和我FooChanger设有工厂,我想用换由FooFactory对象创建的对象,然而,Scala是无法识别该类型myOwnChanger.fooFactory.Foofactory.Foo是相同的。

一个可能的解决方案是在所有客户端代码中投射或仅使用factory.theFooChanger.fooFactory。两者都是丑陋的解决方案,并迫使客户做一些不自然的事情。

问题是:可以做些什么来避免客户端的问题?有没有办法告诉推理者,其余代码myOwnChanger.fooFactory.Foofactory.Foo是一样的?

class FooChangerFactory(val fooFactory: FooFactory) { 
class FooChanger 
    def change(foo: fooFactory.Foo) = foo 
} 

class FooFactory(i: Int) { 
    class Foo private[FooFactory]() 

    def create = new Foo 
    def theFooChanger = new FooChangerFactory(this) 
} 

val factory = new FooFactory(1) 
val myFoo = factory.create 
val myOwnChanger = factory.theFooChanger 
myOwnChanger.change(myFoo) // error here! it expects myOwnChanger.fooFactory.Foo 

回答

3

替换

def change(foo: fooFactory.Foo) = foo 

def change(foo: FooFactory#Foo) = foo 

存在的问题的原因,在Scala中,内类型是路径依赖性(即,对于每个FooFactory例如,其内型Foo对此是“独一无二的”)。 #的用法被称为type projection。要想到这一点,FooFactory#Foo是在所有FooFactory的实例中所有与路径有关的Foo的常见超类型。