0

次の ApplContext クラスが 1 つあります。
http://codetidy.com/4498/ (これは 400 行のファイルです。このファイルをすべて読む必要はありません。)

次のクラスはクラスの上に拡張されています。

public class validatorApplContext extends ApplContext {

    private static final String FAKE_FILE_NAME = "file://";
    private static final String USER_MEDIUM_ALL = "all";
    private static final String CSS_VERSION_3 = "css3";
    private static final String PROFILE_NONE = "none";
    private static final int DEFAULT_WARNING_LEVEL = 0;

    public validatorApplContext(String lang) {
        super(lang);
    }
}

これで、ApplContext オブジェクトを返す別のクラスができました。

public class ApplContextFactory {

    private static final String FAKE_FILE_NAME = "file://";
    private static final String USER_MEDIUM_ALL = "all";
    private static final String CSS_VERSION_3 = "css3";
    private static final String PROFILE_NONE = "none";
    private static final int DEFAULT_WARNING_LEVEL = 0;

    public static ApplContext getApplContext(String lang) {
        ApplContext ac = new ApplContext(lang);
        ac.setWarningLevel(DEFAULT_WARNING_LEVEL);
        ac.setCssVersion(CSS_VERSION_3);
        ac.setProfile(PROFILE_NONE);
        ac.setMedium(USER_MEDIUM_ALL);
        ac.setFakeURL(FAKE_FILE_NAME);
        ac.setTreatVendorExtensionsAsWarnings(true);
        return ac;
    }
}

私がやっているとき、今ApplContextFactoryクラスで

ApplContext ac = new ApplContext(lang);

クライアント側のすべてが完全に正常に機能しています。しかし、私がやっているとき

ApplContext ac = new validatorApplContext(lang);

動作していません。継承が何らかの問題を引き起こしているようです。

問題を特定できる場合は、助けてください。

ありがとう。

4

2 に答える 2

2

Java では、属性を持つクラスがある場合、メソッドでできるように、継承中にそれをオーバーライドすることはできません。属性の動作が異なるだけです。

同じ名前の別の属性を追加できます。これがあなたが行ったことです。したがって、ApplContextFactory には FAKE_FILE_NAME という名前の 2 つのフィールドがあり、1 つは ApplContextFactory で定義され、もう 1 つは validatorApplContext で定義されています。どちらが読み込まれるかは、メソッドのようにインスタンス タイプに依存しません。参照のタイプのみに依存します。そう:

// an object with two FAKE_FILE_NAME attributes
validatorApplContext vac = new validatorApplContext ();
ApplContext AC= ac; // the same object, just a different variable

System.out.println(v.FAKE_FILE_NAME) //  this reads from validatorApplContext
ac.FAKE_FILE_NAME = "test"; // this sets in ac, because this is the type of the variable
System.out.println(v.FAKE_FILE_NAME) //  no change visible here
System.out.println(ac.FAKE_FILE_NAME) //  change visible here.

メソッドへのアクセスは動的 (実行時に利用可能な情報を使用) であり、属性へのアクセスは静的 (コンパイル時に利用可能な型のみを使用) であると言うかもしれません。ポリモーフィズムを使用する場合は、メソッドを使用する必要があります。

あなたの場合、ApplContext のすべてのコードは FAKE_FILE_NAME の元の値を認識し、validatorApplContext 内のすべてのコードはコンストラクターで設定された値を認識します。

最も簡単な解決策は、ゲッターとセッターを両方のクラスに追加することです (静的ではありません!)。これにより、すべての静的フィールドを取得および設定します。ゲッターは互いにオーバーライドします。しかし、属性のコピーが 2 つ残っているので、これは本当にやりたいことではないようです。

率直に言って、コードは少し間違っているように見えます。スクリプト言語で大きな経験があり、最初の大規模なプロジェクトを Java で構築しようとしたかのように、実際には適合せず、言語の粒度に反する慣行に従います。もしそうなら、もっと多くの問題が予想されます。

于 2013-01-25T07:21:15.143 に答える
0

クライアントが次のようなことをした場合:

ApplContext ac = ApplContextFactory.getInstance(language); logger.log(ac.DEFAULT_WARNING_LEVEL, message);

これにより、実行時に ac の型が ValidatorApplContext であっても、ApplContext で定義された DEFAULT_WARNING_LEVEL の値が取得されます。静的参照のバインディングはコンパイル時に決定され、ac は宣言された型として ApplContext を持ちます。

于 2013-01-27T08:18:33.677 に答える