6

私はここで問題に悩まされています。サブクラス(子)のスーパークラス(親クラス)の属性からセッターを変更したいのですが、サブクラスでこのメソッドをオーバーライドすると、スーパークラスのプライベート属性にアクセスできません。そして重要なのは、彼らはプライベートにとどまらなければならないということです。

スーパークラス(問題:setMinimumVoorraad(int voorraad);)

パッケージドメイン;

public abstract class Artikel implements Weegbaar
{
    private String omschrijving;
    private double prijs;
    private int aantalInStock;
    private int minimumVoorraad;

    public Artikel(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad)
    {
        this.setOmschrijving(omschrijving);
        this.setPrijs(prijs);
        this.setAantalInStock(aantalInStock);
        this.setMinimumVoorraad(minimumVoorraad);
    }

    @Override
    public String toString()
    {
        String output = String.format(" \n omschrijving: %s \n prijs:  %f \n In stock %d (minimumvoorraad = %d) \n", this.omschrijving, this.prijs, this.aantalInStock, this.minimumVoorraad);
        return output;
    }
//----Getters----
    public String getOmschrijving() {
        return omschrijving;
    }

    public double getPrijs() {
        return prijs;
    }

    public int getAantalInStock() {
        return aantalInStock;
    }

    public int getMinimumVoorraad() {
        return minimumVoorraad;
    }

//----Setters----
    public void setOmschrijving(String omschrijving) {
        this.omschrijving = omschrijving;
    }

    public void setPrijs(double prijs) {
        this.prijs = prijs;
    }

    public void setAantalInStock(int aantalInStock) {
        this.aantalInStock = aantalInStock;
    }

    public void setMinimumVoorraad(int minimumVoorraad) 
    {
        if(minimumVoorraad < 2)
            this.minimumVoorraad = 3;
        else
            this.minimumVoorraad = minimumVoorraad;
    }


}

サブクラス

package domein;


public class Food extends Artikel
{

    private String houdbaarheidsDatum;
    private double nettoGewicht;

    public Food(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad, String houdbaarheidsDatum, double nettoGewicht)
    {
        super(omschrijving, prijs, aantalInStock, minimumVoorraad);
        this.setHoudbaarheidsDatum(houdbaarheidsDatum);
        this.setNettoGewicht(nettoGewicht);
    }

    @Override
    public boolean isWeegbaar()
    {
        return true;
    }


//----Getters----
    public String getHoudbaarheidsDatum() {
        return houdbaarheidsDatum;
    }

    public double getNettoGewicht() {
        return nettoGewicht;
    }

//----Setters----
    public void setHoudbaarheidsDatum(String houdbaarheidsDatum) {
        this.houdbaarheidsDatum = houdbaarheidsDatum;
    }

    public void setNettoGewicht(double nettoGewicht) {
        this.nettoGewicht = nettoGewicht;
    }

    @Override
    public void setMinimumVoorraad(int minimumVoorraad) 
    {
        if(minimumVoorraad < 5)
            this.minimumVoorraad = 6;
        else
            this.minimumVoorraad = minimumVoorraad;
    }


}

私を助けることができる誰か?前もって感謝します。

4

2 に答える 2

10

1つの可能性は、スーパークラスのセッター(おそらく、アクセスできる)の観点からサブクラスのセッターを実装することです。

たとえば、セッターがsetFooであるとすると、サブクラスのバージョンは次のようになります。

public void setFoo(Foo f) {

    // Do subclass stuff pre-setting, if any

    super.setFoo(f);

    // Do subclass stuff post-setting, if any
}
于 2013-03-26T07:41:01.440 に答える
3

NPEによる上記の回答は、この問題を解決するための最善の方法です。これはエレガントで、スーパークラスとサブクラスの間の基本的な継承契約を尊重します。元の投稿でも、サブクラスは実際にはスーパークラスよりも制限が厳しいため、次のようにします。

@Override
public void setMinimumVoorraad(int minimumVoorraad) 
{
    if(minimumVoorraad <= 5)
        super.setMinimumVoorraad(6);
    else
        super.setMinimumVoorraad(minimumVoorraad);
}

NPEが提案したとおりに、おそらく機能します。(ifテストをどのように変更したかに注意してください。タイプミスかどうかはわかりませんが、元の実装5では有効な最小値になりますが、like4を入力すると設定され6ます。)

他の(おそらく許容できる)パターンは次のとおりです。

  1. 親クラスのメンバーを作成しますprotected。これにより、可視性が得られます。(制限について言及したことを認識してくださいprivate。このパターンは、より完全な全体的な回答を提供するためにのみ言及されています。)
  2. 検証ロジックを別のメソッド(非プライベート)に委任します。このようにして、子は検証メソッドをオーバーライドできます。

次に、Javaリフレクションを使用する(おそらく受け入れられない)パターンに移ります。

@Override
public void setMinimumVoorraad(int minimumVoorraad) {

    try {
        Field field = this.getClass().getSuperclass().getDeclaredField("minimumVoorraad");
        field.setAccessible(true);

        if(minimumVoorraad <= 5)
            field.set(this, 6);
        else
            field.set(this, minimumVoorraad);

        field.setAccessible(false);
    }
    catch(NoSuchFieldException | IllegalAccessException e) {
        // do something
    }
}

あなたがあなたの人生全体でこれを決してやらないならば、あなたはおそらくそれのためにより良いであろうということは注目に値します。すべてのコントラクトを完全に破るだけでなく、ハードコードされた文字列に依存してフィールド名のルックアップを実行しますが、それ自体はかなり面倒です。しかし、それは存在します。そして、何かをしない方法の例がなければ、良い答え(すでにNPEによって上に与えられている)は完全ではありません...

于 2013-03-26T11:00:23.367 に答える