1. ホーム
  2. java

[解決済み] Java の `final` メソッド:何を約束するのか?

2022-04-29 10:11:39

質問

Java のクラスでは、メソッドを次のように定義することができます。 final は、このメソッドがオーバーライドされてはならないことを示すものです。

public class Thingy {
    public Thingy() { ... }
    public int operationA() {...}
    /** this method does @return That and is final. */
    public final int getThat() { ...}
}

それは明らかで、偶発的なオーバーライドから保護したり、パフォーマンスを向上させたりするために役立つかもしれません。

私の疑問は OOPの観点から、私は、メソッド final クラスデザイナーは 約束 このメソッドは、常に記述された、あるいは暗示されたとおりに動作します。しかし、しばしばこれはクラスの作者の影響外である場合があります。 プロパティ .

構文的な制約は明確ですが、OOP的な意味合いではどうなのでしょうか?はたして final は、ほとんどのクラス作成者がこの意味で正しく使用しているのでしょうか?

はどのような契約なのでしょうか? final メソッドは約束しますか?

どのように解決するのですか?

前述のとおりです。 final は、Javaメソッドで使用され、そのメソッドがオーバーライド(オブジェクトスコープの場合)または非表示(静的の場合)できないことを示します。これにより、元の開発者はサブクラスによって変更されない機能を作成することができ、それが保証されるだけです。

これは、メソッドが非公開フィールドやメソッドなど、カスタマイズ可能な他のコンポーネントに依存している場合、最終的なメソッドの機能がまだカスタマイズ可能である可能性があることを意味します。しかし、これは(ポリモーフィズムによって)部分的なカスタマイズが可能になるため、良いことです。

何かをカスタマイズできないようにする理由には、以下のようなものがあります。

  • <強い パフォーマンス -- コンパイラの中には、特に副作用のない操作を解析して最適化できるものがあります。

  • カプセル化されたデータを取得する -- イミュータブルオブジェクトは、構築時に属性が設定され、決して変更されることのないオブジェクトです。あるいは、その属性から計算された値。良い例として、Javaの String クラスがあります。

  • 信頼性と契約 -- オブジェクトは、プリミティブ( int , char , double など)および/または他のオブジェクト。これらの構成要素に適用可能なすべての操作が、より大きなObjectで使用される場合にも適用可能であり、論理的であるべきとは限らない。メソッドに final 修飾子を使用すると、それを確実にすることができます。Counterクラスが良い例です。


public class Counter {
    private int counter = 0;

    public final int count() {
        return counter++;
    }

    public final int reset() {
        return (counter = 0);
    }
}

もし public final int count() メソッドが final というようなことができます。

Counter c = new Counter() {   
    public int count() {
        super.count();   
        return super.count();   
    } 
}

c.count(); // now count 2

あるいはこんな感じ。

Counter c = new Counter() {
    public int count() {
        int lastCount = 0;
        for (int i = super.count(); --i >= 0; ) {
            lastCount = super.count();
        }

        return lastCount;
    }
}

c.count(); // Now double count