2

クラスを拡張し、拡張されたクラスのインスタンスから値をコピーしたいので、新しいクラスですべてのパラメーターを取得します。これが意味をなさない場合、私がやろうとしていることの簡単な例:

public class MyTableModel extends DefaultTableModel {

    public MyTableModel(DefaultTableModel model){
        this = (MyTableModel) model; /* I realise this is invalid */
    }

    public newMethod(){
        // Some additional code
    }
}

これを達成することは可能ですか?

4

3 に答える 3

3

継承ではなく合成が必要なようです。特に、デコレータ パターンを使用しようとしているようです。つまり、 の既存のインスタンスを取得し、ほとんどのメソッドを基になるデリゲートに転送する別のインスタンスを作成しますが、おそらくいくつかの機能を追加/変更/装飾します。DefaultTableModelDefaultTableModel

を設定することはできませんが、必要に応じていくつかのメソッドを追加/装飾して、ほとんど/すべてのリクエストを に転送this = somethingElse;できます。DefaultTableModel delegatedelegate

こちらもご覧ください

  • 有効な Java 2nd Edition、項目 16: 継承よりも構成を優先する

グアバの例:ForwardingCollection

このパターンの例はForwardingCollectionGuava からのものです:

すべてのjava.util.Collectionメソッド呼び出しを別のコレクションに転送する 。サブクラスは、1 つ以上のメソッドをオーバーライドして、デコレータ パターンごとに必要に応じてバッキング コレクションの動作を変更する必要があります。

ソース コードを見て、このパターンが通常どのように実装されているかを確認できます。

  @Override protected abstract Collection<E> delegate();

  public int size() {
    return delegate().size();
  }    
  public boolean isEmpty() {
    return delegate().isEmpty();
  }
  public boolean removeAll(Collection<?> collection) {
    return delegate().removeAll(collection);
  }
  // many more interface Collection methods implemented like above...

ご覧のとおり、すべてのメソッドをその、別のに転送ForwardingCollectionするだけです。当然のことながら、これはかなり反復的でありふれたコードを書くことですが、サブクラスは簡単に装飾したいものだけを装飾することができます。implements Collectiondelegate()Collectionextends ForwardingCollection

于 2010-07-28T15:21:13.413 に答える
1

Java でこれを何かに設定することはできません。現在のオブジェクトを初期化するためにコンストラクターの(this == someObject)ように、またはコンストラクター内で現在使用されているオブジェクトのプロパティにアクセスするなどの式に使用されるだけです。キーワードについて(this.someProperty)詳しくはこちらthis

このコードは、おそらくjava.lang.ClassCastException

それはMyTableModelですが、DefaultTableModelDefaultTableModelはありませんMyTableModel。Java での型変換の詳細については、http://java.sun.com/docs/books/jls/third_edition/html/conversions.htmlを参照してください。

サブクラスで親クラスから再利用したい状態や動作がある場合は、それらのメンバーを としてマークするprotectedか、他の形式の構成を検討する必要があります。

于 2010-07-28T15:30:29.500 に答える
0

これを行うより良い方法は、protected代わりにスーパークラスのフィールドを作成privateすることです-これにより、サブクラスでそれらにアクセスできるようになります。

サブクラスのコンストラクターを定義した場合、スーパークラスからもコンストラクターを呼び出す必要があることに注意してください。そのため、その点では、必要なすべての変数を引き続き渡すことができます。

また、スーパークラスのすべてのパブリック メソッドは、サブクラスのインスタンスを持つ任意のコードからそのまま呼び出すことができることを忘れないでください。

編集:ちょっとした例が役立つかもしれません:

public class DefaultTableModel
{
    protected String modelName;
    protected int numberOfTables;
    private numTimesReinited = 0;

    public DefaultTableModel(String name, int numTabs)
    {
        modelName = name;
        numberOfTables = numTabs;
    }

    public void reinit()
    {
        numTimesReinited++;
        // Other stuff
    }

    protected int getNumberOfReinits()
    {
        return numTimesReinited;
    }

    public String getName()
    { 
        return name;
    }
}

 

public class MyTableModel extends DefaultTableModel
{
    private String modelType;

    public MyTableModel(String name, int numTables, String modelType)
    { 
        super(name, numTables); // sets up the fields in the superclass
        this.modelType = modelType;
    }

    // purely "local" code
    public void getModelType()
    {
        return modelType;
    }

    // Accesses several protected data to provide new (public) functionality
    public void addTable()
    {
        if (getNumberOfReinits() < 10)
        {
           numberOfTables++;
           reinit();
        }
    }
}

要件を誤解している場合はお知らせください。ただし、スーパークラスのフィールドと動作にアクセスしたいようです。そうでない限り、サブクラスで自動的にアクセスできますprivate

于 2010-07-28T15:20:42.730 に答える