2017-02-11 13 views
1

私はちょうど微妙な罠を見つけました。Javaではコンストラクタで抽象メソッドを使用しないでください。

/** 
* Innocent-looking example that causes trouble. See {@link B}. 
* 
*/ 
public abstract class A { 

    abstract String someStringLeftForExtensionsToSpecify(); 

    public A() { 
     super(); 
     processString(someStringLeftForExtensionsToSpecify()); 
    } 

    void processString(String string) { 
     // do complicated things with string that are shared by all extensions 
     // so this could should be here. 
    } 
} 

/** 
* Looks innocent enough, but abstract method is used in {@link A}'s constructor before 
* property is set, even though it uses property. 
*/ 
public class B extends A { 

    private int property; 

    public B(int property) { 
     this.property = property; 
    } 

    public String someStringLeftForExtensionsToSpecify() { 
     if (property == 13) { 
      return "Unlucky"; 
     } 
     return "Lucky"; 
    } 
} 

コンストラクタ内の抽象メソッドを使用すると、OOPのno-noになるはずです。 Javaはこれを禁じるべきではありません、同じ方法で、 "super"への引数として "this"または非静的メソッドの使用を禁じますか?これはよく知られていることだろうか。

+4

'A' **の実際のランタイムインスタンスが**何であるか混乱しています。実行時には、指定されたメソッドを実装する具象型でなければなりません。これが '抽象'型です。 –

+2

これは潜在的な罠なのです。さらに一般的です。非最終的な方法は不可能です。なぜ彼らがそれを許さないのか分からない。おそらく言語の単純さのために、それはちょうど推測です。 – yshavit

+2

NetBeans IDEで警告が表示されます。 –

答えて

0

コンストラクタ内の抽象メソッドを使用すると、 OOP内にno-noがあるようです。 Javaはこれを禁じるべきではない、同じ方法で "super"への引数として "this"または非静的メソッドの使用を禁じるか?私は これがよく知られているものかどうか疑問に思います。

質問は、Javaがthisに問題があることを理由に、クライアントのメソッドに引数があるよう

(これはEclipseで 罰金をコンパイルする)ことを禁止すべきかどうかについてですクライアントが、完全に構成されていないオブジェクトへの参照を受け取る、すなわち、不整合な状態にある、および/またはその不変量が損なわれていないという重要なリスクがあること。コンパイラはthisが無効な状態であると警告しています。

しかし、コンストラクタ内から非最終的なメソッドを呼び出すことは危険ですか? thisをメソッドに渡していない場合は、無効な状態のオブジェクトへの参照を受け取っていません。

危険性がありますか?場合によります。変更可能または安全なオブジェクトへの参照が悪質なクライアントによって傍受される可能性がある場合は、確かに。しかしこれは、単にコンストラクタではなく、アプリケーション全体の設計におけるセキュリティの考慮事項と関係しています。

いくつかの状況では、オブジェクト指向プログラミングでは多態性がno-noではないため、コンストラクタがオーバーライド可能で非最終的なメソッドを呼び出すことが望ましい場合もあります。

本当の問題はアクセシビリティです。エンジニアは、クライアントにアクセスさせたくないメソッド(最終または非最終)をAPIにエクスポートしてはなりません。

関連する問題