我在Scala中有这个代码
当我定义a
值时,我也会调用像setStr
这样的对象中的一些方法,它非常有用且令人惊叹。但是当我将AClass
定义为final时,编译器将抛出异常作为final final的非法继承。在某些情况下,我应该使用final类,在类启动后调用这种类型的方法对我来说非常有用,我的问题是如何解决这个问题
test("Test function call") {
val a: AClass = new AClass {
setStr("Pooya")
func1(this)
}
}
class AClass { // when I declare the class final, the compiler will raise an error
private var str:String=""
def setStr(str:String)={
this.str=str
}
def aMethod() = print(str)
}
def func1(a: AClass) {
a.aMethod()
}
答案 0 :(得分:3)
执行new AClass { ... }
时,您正在创建扩展此类的匿名类。当一个类为final
时,它无法扩展。
做你想做的事的一种方法就是:
val a: AClass = new AClass
import a._
setStr("Pooya")
func1(this)
按照@ Vladimir的建议,稍微清洁的方式:
val a: AClass = { val a = new AClass
import a._
setStr("Pooya")
func1(this)
a
}
现在,您可以根据需要多次重复此操作,而不会使setStr
模糊不清。对于func1
及其当前定义,如果它位于{}
块中,则无关紧要。
答案 1 :(得分:1)
要获得final
语义,请将初始状态传递给构造函数。
另一种模式是使用早期定义。请注意,BClass #strs是最终的。
最终意味着当您的初始化程序完成时,该值不得更改。
并且失去了可变状态。
但是如果你喜欢或需要可变性,那么伴侣对象上的工厂可以在构建对象时运行你需要的任何理智。
package inheritthewind
object Test extends App {
val a = new AClass(new AInit { val str = "Pooya" })
a.aMethod()
val b = new {
val str: String = "Pooya"
} with BClass
b.aMethod()
val b2 = new BClass {
val str: String = "Pooya"
}
b2.aMethod() // uh no, result is "nulls"
val c = CClass(new CPrototype { val str = "Pooya" })
c.aMethod()
// not allowed
//val nope = new CClass
}
trait AInit {
def str: String
}
final class AClass(init: AInit) {
private final val str: String = init.str
def aMethod() = Console println str
}
abstract class BClass {
val str: String
final val strs = str + "s"
def aMethod() = Console println strs
}
trait CPrototype extends AInit
final class CClass private() {
private var str: String = _
def aMethod() = Console println str
}
object CClass {
def apply(p: CPrototype): CClass = {
val res = new CClass
res.str = p.str
res
}
}
和
scala> :javap -pv inheritthewind.BClass
[snip]
private final java.lang.String strs;
flags: ACC_PRIVATE, ACC_FINAL
public abstract java.lang.String str();
flags: ACC_PUBLIC, ACC_ABSTRACT
public final java.lang.String strs();
flags: ACC_PUBLIC, ACC_FINAL