在Scala中,有很多方法可以创建对象:
例如,使用新关键字
创建课程class Car {
def startEngine() = println("run....")
}
val car = new Car
car.startEngine() // run....
其中car对象应该像堆中的Java座位中的“newed”对象一样,并且在被取消引用时等待垃圾收集。
那么,如何创造特质呢?
trait Car {
def startEngine() = println("run...")
}
val car = new Car {}
car.startEngine() //run....
这是一个有效的语法,使用类myCar扩展Car创建对象。 相反,它只是从Trait创建对象。
它是否反对堆中的座位? (我猜不是) 那么,它是否存在于堆栈中并且一旦从scoop中被取消引用为局部变量?
最后,如何通过对象?
object Car {
def startEngine() = println("run...")
}
Car.startEngine() //run....
这与via Trait相同吗?我相信对象更有可能生活在堆栈中。
有人可以就内存分配方面的这三种语法之间的区别进行阐述吗?
答案 0 :(得分:7)
他们都住在堆里。 (另外,你的第二个例子没有按照书面形式工作。)
区别在于代码重用。
使用类,该类的每个新对象都运行相同的代码:
class Car { }
val c1 = new Car
val c2 = new Car // Same code as c1
c1.getClass == c2.getClass // true
c1 eq c2 // false--different objects on the heap
使用特征,每次从中创建一个类时,它都会复制代码(至少是一个转发器)。因此效率较低但更灵活(因为您可以在需要时将其混合到其他类中)。而且你可以通过添加{}
为每个对象创建一个新的匿名类,因此很容易做很多工作:
trait Car { }
val t1 = new Car {} // Anon class #1
val t2 = new Car {} // Anon class #2--duplicate of #1
t1.getClass == t2.getClass // false
对于一个对象,你明确地说只会有一个。你不能(没有低级别的欺骗)得到另一个。
object Car { }
val o1 = Car
val o2 = Car
o1 eq o2 // true -- there is only one Car
答案 1 :(得分:1)
使用类(案例1)或实现特征的匿名类(案例2)在内存方面应该是相同的。请注意,您永远不能直接实例化特征。例如,new Car
不起作用,只有new Car {}
实例化一个扩展该特征的匿名类。
使用单例对象显然只使用该“类”的一个实例。我不认为顶级对象会被垃圾收集,所以你不应该在单例对象中存储大量数据。