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

一种可能性是根据超类的 setter 来实现子类的 setter(大概您可以访问)。

例如,假设 setter 是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. 在您的 Parent 类中创建成员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 回答