正当我开始熟悉界面时,我遇到了一个带抽象类的绊脚石。根据我的理解,它们可用于为子类提供一些功能,但强制子类指定未定义的函数(如果有任何剩余的)。
我遇到的所有示例只涉及可能是静态的功能 - 没有引用实例变量。
我试图在抽象类中隐藏一些常见函数,例如getName()
,但是能够在子类中定义所述名称。
public interface Application {
public String getName();
}
/**
* Specify some default behaviour to keep leaf classes free of common code
*/
public abstract class DefaultApplication implements Application {
public static final String NAME = "DefApp";
@Override
public String getName() {
return NAME;
}
}
public class MyApp extends DefaultApplication {
public static final String NAME = "My App";
}
// Main class
Application myApp = new MyApp();
System.out.println(myApp.getName()); // Prints "DefApp"
我认为protected String name
可能有效,但这也会在抽象类中返回实例变量。唯一的解决方案是在每个子类中重新定义getName()
吗?我不会那么想,但这不是我试图将方法吸收到抽象类中的唯一情况。
谢谢!
编辑:
如果它是相关的(建议我可以考虑的其他方法),Application是一个插件api,MyApp是一个提供的示例应用程序。 DefaultApplication是基础项目的一部分。
答案 0 :(得分:3)
你不能覆盖任何静态的东西。静态方法不属于特定对象,而是属于类本身;当您编写return NAME
时,编译器会将其读为return DefaultApplication.NAME
。
在这种情况下,你可以像你已经提出的那样覆盖每个子类中的getName()
,或者你可以使该字段非静态,并执行以下操作:
abstract class DefaultApplication implements Application {
private final String name;
protected DefaultApplication(String name) {
this.name = name;
}
protected DefaultApplication() {
this("DefApp");
}
public String getName() {
return name;
}
}
class MyApp extends DefaultApplication {
public MyApp() {
super("My App");
}
}
这将为DefaultApplication
的每个实例添加一个额外的字段,但只要你没有数百万个,这应该不重要。
答案 1 :(得分:2)
注释想法让我感兴趣,所以我想我会把它扔出去。这是一个非常复杂且不完全推荐的打印“我的应用程序”的方式:
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
interface Application {
public String getName();
}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface ApplicationName {
String value();
}
@ApplicationName("DefApp")
abstract class DefaultApplication implements Application {
@Override
public String getName() {
return getClass().getAnnotation(ApplicationName.class).value();
}
}
@ApplicationName("My App")
class MyApp extends DefaultApplication {
}
public class Main {
public static void main(String[] args) {
Application myApp = new MyApp();
System.out.println(myApp.getName());
}
}