0

就在我开始熟悉接口时,我遇到了抽象类的绊脚石。在我的理解中,它们可以用来为子类提供一些功能,但强制子类指定未定义的函数(如果有的话)。

然而,我遇到的所有示例都只处理可能是静态的功能 - 没有引用实例变量。

我试图隐藏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 是基础项目的一部分。

4

2 回答 2

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但只要您没有数百万个实例,这并不重要。

于 2012-12-14T21:36:35.597 回答
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());
  }
}
于 2012-12-14T22:00:40.143 回答