2017-12-29 11 views
1

サブクラスが完全に初期化された後、サブクラスからスーパークラスへ通知を自動的に送信する方法はありません。 i。 e。サブクラスコンストラクタの終了後?スーパークラスにサブクラスの作成について通知する

MOTIVATION

基本クラスは、クラスのフィールドの一覧で作業しているいくつかのデフォルトのメソッドを提供しなければなりません。サブクラスフィールドはサブクラスの作成後にのみ親クラスでアクセス可能であるため、基本クラスはこれらのサブクラスフィールドを基本クラスコンストラクタで読み取ることができません。 1つの解決策は、これらのフィールドを処理する必要がある各基本メソッドの初めにサブクラスフィールドを読み込むことです。反射が遅いために、遅延初期化を使用する方がよいでしょう。

コールバックメカニズムがJavaに存在しない場合は、「サブクラス作成コールバック」を定義できるようになります。これらのフィールドを遅延初期化を使用せずに初期化することができますより良い保守性

オブジェクトeの割り当て解除を追跡することは可能です。 g。 finalize()またはReferenceQueueを介して、私はオブジェクトの作成に類似したものがあるかどうかを知りたいと思います。

は、データベースEntityクラスを作成したいとし(私はこれのためのORMベースのソリューションがある知っているが、これは同様の問題の説明のためだけである)のようなSQL文を生成することができるようになりますエンティティのクラスフィールドに基づいて、CREATE TABLE、INSERT、UPDATE、DELETEしたがって、基底クラスはクラスフィールドの読み込みと、これらのステートメントの生成を担当します。

class Entity { 
    public String getCreateTableStatement() { 
     // lazy-initialize list of class fields and produce statement... 
    } 

    public String getInsertPreparedStatement() { 
     // lazy-initialize list of class fields and produce statement... 
    } 

    // update, delete, ... 
} 

...サブクラス

public Person extends Entity { 
    @Id public int id; 
    @Column public String name; 
} 

の例を一つだけEntityを拡張し、@Column@Id@AutoIncrement、のようないくつかのフィールドのアノテーションを使用する必要がありますエンティティを作成するには、AIM

遅い初期化を置き換えるには、繰り返しコードの量を減らすのに役立つ別のパターンを使用します。理想的には、サブクラスは他のものを定義する必要はなく、単に「extends Entity」だけです。

+9

この質問は可能[XY問題](http://xyproblem.info/)タイプの質問のように思えます。基本クラスは子クラスを完全に無視し、継承を使用してすべてを解決する必要はありません。構図が良くないと確信していますか? –

+0

@HovercraftFullOfEels与えられた基底クラスから拡張されたサブクラスのクラスフィールドに基づいていくつかのデフォルトメソッドを提供したいと思います。継承は_in situ_です。そうでなければ、各サブクラスで同じメソッドを繰り返す必要があります。 – matoni

+0

または、両方のクラスを同じ親クラスのサブクラスにすることもできますが、それでも構図で関連付けることができます。この魚には多くの方法があります。 –

答えて

2

あなたがしようとしていることは少しはっきりしていますが、一般に、オブジェクト作成に関連する多くの問題は、作成プロセスをカプセル化するfactory methodを使用することで解決できます。 (他の人が指摘したように)、継承はあなたの問題のために最善の解決策ではないかもしれないことを

public static MySubClass createSubClass() { 
    MySubClass subClass = new MySubClass(); 
    subClass.baseClassMethodThatManipulatesFields(); 
    return subClass; 
} 

注:この方法では、あなたは、単一のコンストラクタ呼び出しで実現できる以上のことを行うことができます。 Entityにリストするメソッドは、おそらくクラスを初期化するためにリフレクションを使用するファクトリの責任であるべきです。

+0

これは、Javaがいくつかの作成コールバックをサポートしているかどうかという疑問に答えるものではありませんが、私はこの解決策が好きなので、数日後にこの回答を受け入れるでしょう。ありがとう! – matoni

+0

私はそのようなコンストラクタのコールバックがJavaでは存在しないと思っていますが、もちろん、ファクトリメソッドに組み込むこともできます。 –

0

私はなぜ尋ねていません。あなたが答えてくれるようにしたいのであれば、親オブジェクトはコンストラクタを介してその子に完全にアクセスできます。はい、私はこの時点で子オブジェクトが完全に初期化されていないことを知っていますが、このステップでは注釈情報が利用可能です。

これは一例です:

import org.apache.commons.lang3.reflect.MethodUtils; 

import javax.persistence.Id; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.AccessibleObject; 
import java.util.ArrayList; 
import java.util.List; 

    public class Entity { 
     protected Entity() { 
      List<AccessibleObject> ids = getAccessibleObjectWithAnnotation(Id.class); 
      List<AccessibleObject> columns = getAccessibleObjectWithAnnotation(Column.class); 
     } 

     private List<AccessibleObject> getAccessibleObjectWithAnnotation(Class<? extends Annotation> cls) { 
      List<AccessibleObject> res = new ArrayList<>(); 
      res.addAll(FieldUtils.getFieldsListWithAnnotation(getClass(), cls)); 
      res.addAll(MethodUtils.getMethodsListWithAnnotation(getClass(), cls)); 
      return res; 
     } 
    } 
関連する問題