鉴于以下内容:
class TestClass extends TestTrait { def doesSomething() = methodValue + intValue } trait TestTrait { val intValue = 4 val unusedValue = 5 def methodValue = "method" def unusedMethod = "unused method" }
当上面的代码运行时,TestClass实际上是否将内存分配给unusedValue或unusedMethod?我已经使用了javap并且我知道存在一个unusedValue和一个unusedMethod,但是我无法确定它们是否实际上填充了任何类型的状态或内存分配.
基本上,我试图理解一个类总是得到一个特征提供的所有,或者编译器是否足够聪明,只提供该类实际使用的特征?
如果一个特质总是强加于一个类,它似乎可能是低效的,因为我希望许多程序员将使用特征作为mixins,因此在任何地方浪费内存.
感谢所有阅读并帮助我深究这一点的人!
解决方法
一般来说,在Scala,Java和C等语言中,每个类都有一个指向其实例方法的指针表.如果你的问题是Scala编译器是否会在方法表中为unusedMethod分配插槽,那么我会说是的.
我想你的问题是Scala编译器是否会查看TestClass的主体并说“哇,我只看到methodValue和intValue的使用,所以作为一个好的编译器,我将避免在TestClass的方法表中为unusedMethod分配空间但是它通常不能真正做到这一点.原因是,TestClass将被编译成一个类文件TestClass.class,这个类可能被程序员用在库中,你甚至不知道.
他们想和你的班级做什么?这个:
var x = new TestClass(); print(x.unusedMethod)
看,问题是编译器无法预测将来会使用这个类的人,因此它将所有方法放入其方法表中,甚至是那些未被类中其他方法调用的方法.这适用于在类中声明的方法或通过实现的特征拾取的方法.
如果您希望编译器在固定的封闭系统上进行全局系统范围的静态分析和优化,那么我认为理论上它可以减少这些事情,但我怀疑这将是一个非常昂贵的优化,并不值得.如果您需要这种节省内存的话,最好自己编写较小的特性.