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()各サブクラスで再定義する唯一の解決策はありますか? 私はそれほど気にしませんでしたが、メソッドを抽象クラスに吸い上げようとしているのはこれだけではありません。

ありがとう!

EDIT:
関連する場合(私が検討できる他のアプローチを提案するため)、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 に答える