2012-03-07 19 views
1

在Scala中,可以在构造函数中定义类属性。但是一旦你声明了它们,就不可能再改变行为了(getters和setter),就像在类体中声明时一样?构造函数定义属性的Scala限制

例子:

class MyExample(var attribute : String) 
{ 
    def attribute() //trying to override getter <- doesn't work 
} 

class MyExample(theAttribute : String) 
{ 
    def attribute = theAttribute //overriding default accessor (was var) 
} 

如果这是不可能的,为什么会这样?当你向人们展示他们可以很容易地通过在构造函数中设置var或val来创建属性而不关心getter和setter(它们可以在需要时会改变)的情况下,最终发现实际上你应该避免使用这些属性便利的种类。

回答

7

让我们一会儿想象,这是可以覆盖生成的访问器方法:

class MyExample(var attribute : String) 
{ 
    def attribute() = attribute + "abc" // won't compile! 
} 

如果没有进一步的限定它是不可能告诉方法体中的名称attribute是否指的是类字段或递归到方法本身。

通过Scala中的设计方法和字段属于同一个命名空间,这被称为Uniform Access Principle,可以在不破坏外部接口的情况下更改内部实现。

最初的实现可以是:

class MyExample(val attribute : String) 

再变到:

class MyExample (attr :String) { 
    def attribute = attr toUpperCase 
} 

然后

class MyExample(var attribute : String) 

或者

class MyExample(attr : String) { 
    def attribute = attr toUpperCase 
    def attribute_= (a : String) { attr = a + "abc" } 
} 

全部不破坏任何相关代码。

当字段被定义为构造函数的一部分时,自动生成的访问器方法是语法糖。糖减轻了快速原型设计,并有助于保持代码简洁。尽管如此,只要你想添加更多的物质,你就必须使用完整的语法。

+0

非常感谢您的出色答案。对于初学者来说不是那么明显,以至于你可以做这些事情,而书本通常只提供常见的情况。 – 2012-03-07 11:05:17