私は Programming Scala を読んでいます。第4章の冒頭で、著者は、Javaは静的メソッドをサポートしています。これは「純粋ではないOO概念)です。 ?
OOこれまで言及されていない理由の1つは、インターフェイスと抽象クラスが非静的メソッドのみを定義しているためです。静的メソッドは、継承。
静的メソッドは "super
"にアクセスできないことにも注意してください。これは、静的メソッドを実際の意味でオーバーライドできないことを意味します。実際には、それらをオーバーライドすることはできず、非表示にするだけです。これを試して:
_public class Test {
public static int returnValue() {
return 0;
}
public static void main(String[] arg) {
System.out.println(Test.returnValue());
System.out.println(Test2.returnValue());
Test x = new Test2();
System.out.println(x.returnValue());
}
}
public class Test2 extends Test {
public static int returnValue() {
return 1;
}
}
_
これを実行すると、期待どおりの結果が得られません。 Test.returnValue()
は、期待どおりのものを提供します。 Test2.returnValue()
hidesスーパークラス内の同じ名前のメソッド(オーバーライドしません)。期待どおりの結果が得られます。
ポリモーフィズムを使用するために静的メソッドを「非静的に」呼び出すことを単純に期待するかもしれません。そうではありません。変数がどのクラスとして宣言されていても、メソッドの検索に使用されます。誰かがコードが実際に行うこととは異なる何かをすることを誰かが期待するかもしれないので、これは悪い形です。
これは、「静的メソッドを使用しないでください!」という意味ではありません。つまり、シングルトンを作成する遅延方法としてではなく、Classオブジェクトにメソッドを所有させたいインスタンスに対しては、静的メソッドの使用を予約する必要があります。
オブジェクト指向は、およそ3つのことです。
これらの3つのうち、最も重要なものはメッセージングです。
静的メソッドは、少なくともメッセージングと遅延バインディングに違反しています。
messagingの概念は、OOでは、相互にメッセージを送信する自己完結型オブジェクトのネットワークによって計算が実行されることを意味します。メッセージの送信はonly通信/計算の方法です。
静的メソッドはそれを行いません。それらはどのオブジェクトにも関連付けられていません。通常の定義によれば、これらは実際にはメソッドではありません(まったく)彼らは本当に単なる手続きです。 Java静的メソッドFoo.bar
)とBASICサブルーチンFOO_BAR
の間にはほとんど違いがありません。
遅延バインディングについては、より現代的な名前は動的ディスパッチです。静的メソッドもこれに違反します。実際、それはまさにその名のとおりです静的メソッド。
静的メソッドは、オブジェクト指向のいくつかの非常に優れたプロパティを壊します。たとえば、オブジェクト指向システムは自動的に機能セーフであり、オブジェクトは機能として機能します。静的メソッド(または実際にはany statics、静的状態または静的メソッドであること)はそのプロパティを壊します。
また、オブジェクトはメッセージングを介してのみ通信するため、独自のプロセスですべてのオブジェクトを並行して実行することもできます。 (同様にActors、基本的に、これはそれほど驚くべきことではありません。カールヒューイットはSmalltalk-71に基づいて俳優モデルを作成し、アランケイはPLANNERに基づいて部分的にSmalltalk-71を作成しました。 Carl Hewittによって作成されました。アクターとオブジェクトの間の密接な関係は偶然ではありません。実際、それらは本質的に1つと同じです。)繰り返しますが、静的(両方の静的メソッドと特に静的状態)その素敵なプロパティ。
「not-so-pure OO concepts」と「bad練習」を混同しないでください。「pure OO」であることは、あなたが達成しようとするべき万能薬ではありません。静的メソッドがインスタンス変数をパラメータとして取るのは、それらが役に立たないことを意味するわけではありません。オブジェクトに適さないものや、「純粋さ」のためだけに型に押し込まれてはならないものもあります。
物事は「純粋」であるべきだと考える人もいるので、「純粋でない」ものはすべて悪い習慣です。実際には、バッドプラクティスは、混乱しやすく、保守が難しい、使用が難しいなどのことを行っているだけです。インスタンスを取得する静的メソッドの作成これは悪い方法ですインスタンスを取得するメソッドはおそらくインスタンスメソッド。一方、ユーティリティやファクトリ関数のようなものは、通常、インスタンスをとらないので、すべきは静的です。
なぜそれらが「純粋なOO」ではないのか疑問に思っているのなら、それらはインスタンスメソッドではないからです。 "純粋な" OO言語はすべてがオブジェクトであり、すべての関数がインスタンスメソッドです。もちろん、それは常に非常に役立つわけではありません。たとえば、Math.atan2
方法。これは2つの数値を受け取り、状態を必要としません。どのオブジェクトをメソッドにすることもできますof? 「純粋な」OO言語では、Math
自体がオブジェクト(おそらくシングルトン)であり、atan2
はインスタンスメソッドですが、関数は実際にはMath
オブジェクトの状態を使用しないため、「純粋なOO」の概念ではありません。
静的メソッドは密結合を引き起こしますが、これは優れたオブジェクト指向設計の違反です。静的メソッドは本質的に継承やポリモーフィズムなどのオブジェクト指向設計手法をサポートしていないため、呼び出しコードと静的メソッド内のコードの緊密な結合は、依存関係の逆転によって回避できません。
静的メソッドに加えて、これらの緊密に結合された依存関係のためにテストが困難です。これは、データベースなどのコードが依存するサードパーティのインフラストラクチャにつながることが多く、実際に行って変更せずに動作を変更することが非常に困難になりますコード。
静的メソッドは、以下の理由により、適切とは見なされませんOO実践:
1)再利用を妨げる:
静的メソッドはオーバーライドできません。インターフェースでは使用できません。
2)オブジェクトの寿命が非常に長い:
静的メソッドはログ時間の間メモリに残り、そのガベージコレクションには長い時間がかかります。開発者は、静的変数の破棄または作成を制御できません。静的変数を過度に使用すると、メモリがオーバーフローする可能性があります。
3)また、他のいくつかのポイント:
オブジェクトはその状態を完全に制御できないため、カプセル化は考慮されません。制御の反転、疎結合、依存性注入などの概念には従いません。
静的メソッドはそれほど純粋ではありませんOO概念は、オブジェクトが実際に関連付けられていなくても呼び出すことができるためです。クラス自体を使用します。次のように呼び出しますClassname.method(...);
OOの概念は、オブジェクトからのデータの制御/アクセスについての話ですが、静的メソッドはオブジェクトを使用して呼び出す必要はなく、オブジェクトではなくクラスに属しています。
- 乾杯