構成の構文はJavaに役立つ追加機能でしょうか? [閉まっている]
-
05-07-2019 - |
質問
最初に、私は言語理論についてほとんど何も知らず、Java以外の言語をほとんど知りませんが、クールだと思うアイデアがありましたが、皆さんに教えてください:
a:なぜ吸うのか
b:言語xがこれを長年にわたってどのように持ってきたか
c:私の心の吸い方
d:上記のすべて
この構想は、 extends
が行うのと同じ簡単なコード再利用を構成に与えます。
したがって、次のようなクラスがある場合:
public interface A { public void methodInA(); }
そして、次のようなクラスがありました:
public class B { private composed A; public B() { // construct A within constructor } }
これを行うことができます:
B myB = new B(); myB.methodInA();
Bのクラスの委任を追加する必要はありません。ただし、継承の場合と同じこともできます。例:
@Overrides public void methodInA(){ // B's own delegation method }
欠点は次のとおりです。
- メソッドはソースコードに隠されているため、呼び出し元がどこにあるのかわかりにくくなりますが、
extends
の場合も同様です。
- 複合フィールドが同じメソッドシグネチャを共有する場合、競合を解決する必要があります(競合するインターフェイスはどのようにこれを解決しますか?)
- 同じタイプの複数の構成フィールドが必要な場合、どのフィールドに委任するかについて明らかな競合が発生します
- おそらく私が考えていない他の100のこと
言うように、私は明らかに言語理論家ではなく、それについて何年も考えていませんでした。アイデアが頭に浮かんだので、自分がどれだけ間違っているか知りたかったのです。ちょっとクールだと思う。
解決
クラスがこの機能のみを使用して単一のクラスを構成できるように制限すると、ある程度有用であり、議論されている多くの頭痛の種を回避できると思います。
個人的には、具体的なクラスの継承は嫌いです。私はBlochの Effective Java 、継承よりもお気に入り。このようなものは、彼がそのアイテムで推奨するイディオムを実装するのを少し簡単にするだろうと思います。
正直なところ、あなたが何をしているかを本当に知っているなら、これを処理するコンパイラー注釈を書くことができると思います。したがって、インターフェイスIBarを実装するクラスBarがあると仮定すると、クラスは次のようになります。
public class Foo {
@Delegate(IBar.class)
private Bar bar;
// initialize bar via constructor or setter
}
その後、コンパイル中にFooにIBarを実装させることができ、Fooによってまだ実装されていないインターフェイス上のメソッドは、次のように生成されます:
public Baz method1(Qux val) {
return bar.method1(val);
}
前述のように、クラスごとに1つのフィールドのみがこの注釈を使用できるという制限を作成する必要があります。複数のフィールドにこの注釈がある場合、おそらくコンパイルエラーをスローする必要があります。あるいは、何らかの優先モデルをそれに渡されるパラメーターにエンコードする方法を見つけることができます。
これを書きましたが、これはちょっとクールに思えます。たぶん、私は来週それをいじります。なんとか解決できたらこれを更新します。
他のヒント
それはクールに聞こえますが、恐ろしい言語構成要素を作ると思います。同じクラスの複数の「構成」を宣言する場合は明らかに問題がありますが、複数の(異なる)構成クラスのメソッドに呼び出しが一致する場合はどうでしょうか?メインクラスで呼び出されるものを指定する必要があり、そのための追加の構文が必要になります。クラスにパブリックメンバーがいる場合、状況はさらに悪化します。
構成は、多重継承の問題を防ぐために使用されます。このような構成を許可すると、少なくともどのメソッドを呼び出すかを解決するという点で、多重継承が効果的に許可されます。 Javaでの重要な設計上の決定は、(適切な理由で)多重継承を許可しないことであったため、これがJavaに導入されることはまずないと思います。
しかし、これを行うことの明確な利点があるかどうかはわかりません。あなたが言っている点を理解しています。現時点でAのメソッドを呼び出すには、myB.getAInstance()。methodInA()が必要ですが、そのmyB.methodInA()を作成する必要があります。
しかし、Aのインスタンスが複数ある場合はどうなりますか?メソッド呼び出しはどのように解決されますか?多くの場合、構成は1対多の関連付けを意味するため、Bには多くのAインスタンスがあります。それではどうなりますか?
リストされているあなたの不利益に同意します。それは単に価値があるよりも混乱を引き起こす可能性があります。
「Mixins」と呼ばれるものを確認してください。一部の言語では、および「役割」 Perl 5 Moose OOシステムで。
考慮すべき composition と aggregation にも違いがあります。コンパイラは、「is-a」または「has-a」の関係を意味するかどうかをどのように知るのですか?
- オブジェクトグラフ全体がガベージコレクションの対象になりますか、それともグラフの先頭のみになりますか?
複数のORMマッピングツールとそれらの周囲のフレームワークは、永続オブジェクト間の belongsTo
または has-many
の関係を提供し、一部はカスケード削除(作曲用)。あなたが探している単純な構文糖を提供するオフハンドを知りません。
実際には、GroovyのMetaClassとMetaProgrammingのイディオムは、「自動マジック」委任で非常によく似たものを提供するかもしれません。
C ++では複数の継承が許可されています。異なることはわかっていますが、同じ思考プロセスに沿っています。 Javaは、多重継承を許可しないように設計されているため、混乱が少なくなり、バグや悪用が少なくなります。
あなたが提案したことは、Javaの原則と直接対立しています。
そうは言っても、それはクールだろう(必ずしも有用ではない)。私はC ++から切り替えたJavaプログラマーです。私は自分の間違いを犯すことができるのが好きです。