在Scala中,我会编写一个抽象类,其中包含一个抽象属性path
:
abstract class Base {
val path: String
}
class Sub extends Base {
override val path = "/demo/"
}
Java不知道抽象属性,我想知道解决这个限制的最佳方法是什么。
我的想法:
a)构造函数参数
abstract class Base {
protected String path;
protected Base(String path) {
this.path = path;
}
}
class Sub extends Base {
public Sub() {
super("/demo/");
}
}
b)抽象方法
abstract class Base { // could be an interface too
abstract String getPath();
}
class Sub extends Base {
public String getPath() {
return "/demo/";
}
}
你更喜欢哪一个?其他想法?
我倾向于使用构造函数,因为不应该在运行时计算路径值。
答案 0 :(得分:5)
Scala所做的内容就是你所描述的方法B.
采用以下示例类:
abstract class Test{
val path: String
}
使用scalac编译时,它将生成一个抽象的Java类,其中包含一个名为attr的抽象方法,它返回一个String。这可能发生的原因是,因为val是常数,因此它只能通过getter而不是setter来模拟。因此,如果您想从Java访问此类,您可以简单地覆盖抽象的getter方法。
这相当于将生成的Java类(javap的输出):
public abstract class Test extends java.lang.Object implements scala.ScalaObject{
public abstract java.lang.String path();
public Test();
}
答案 1 :(得分:1)
如果path
永远不会改变,我会去选项a,否则我会去选项b。
另一方面是path
的价值在施工时可能无法使用。在这种情况下,选项a被排除在外。但是,与您的Scala代码相比,似乎path
在构建时可用。
答案 2 :(得分:1)
等值为 B ,因为值是固定的。
选项 A 接收构造函数中的路径,并且该值可以在运行时计算,而不是scala示例中的Sub
类是goind。
答案 3 :(得分:0)
您可以尝试创建protected
方法来设置变量的值。只能从同一个包中的类调用。
答案 4 :(得分:0)
我选择选项b,因为如果由于某种原因,路径依赖于其他属性,那么每次另一个属性发生变化时,在超类中设置属性并不是很好。 如果你必须实现getter,那就没问题了。 我想不出任何特定情况,其中选项a更有用。
答案 5 :(得分:0)
两者都可能没问题 - 如果永远不会涉及任何计算,构造函数参数可能更简单(在这种情况下,您可能希望将字段设置为final,这将具有确保由任何其他构造函数设置的额外优势可能会在以后添加);而抽象方法可以让你在将来更改自如。
您也可以将两者结合起来,并在构造函数中设置一个私有字段,并提供访问它的getter的具体(但不是最终)实现。