Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关于基类和派生类的实现问题_Java_Design Patterns_Oop_Inheritance_Polymorphism - Fatal编程技术网

Java 关于基类和派生类的实现问题

Java 关于基类和派生类的实现问题,java,design-patterns,oop,inheritance,polymorphism,Java,Design Patterns,Oop,Inheritance,Polymorphism,我有一个关于实施这一点的最佳方式的问题。我将描述我当前的实现,以及我是如何将自己陷入困境的: 我有一个名为Package的抽象类: public abstract class Package { protected String description; protected String packagingCode; protected Dimension dimensions; protected Weight weight; protected Pa

我有一个关于实施这一点的最佳方式的问题。我将描述我当前的实现,以及我是如何将自己陷入困境的:

我有一个名为Package的抽象类:

public abstract class Package {
    protected String description;
    protected String packagingCode;
    protected Dimension dimensions;
    protected Weight weight;

    protected Package() {
        this.description = null;
        this.packagingCode = null;
        this.dimensions = null;
        this.weight = null;
    }

    protected Package(String description, String packagingCode, Dimension dimensions, Weight weight) throws ShippingException {
        this.description = description;
        this.packagingCode = packagingCode;
        this.dimensions = dimensions;
        this.weight = weight;

        String exceptionMessage = "";

        if(!meetsWeightRequirements()) {
            exceptionMessage = "This package's weight exceeds limits. ";
        }

        if(!meetsDimensionalRequirements()) {
            exceptionMessage += "This package's dimensions exceed limits.";
        }

        if(!StringUtils.isEmpty(exceptionMessage)) {
            throw new ShippingException(exceptionMessage);
        }
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getPackagingCode() {
        return packagingCode;
    }

    public void setPackagingCode(String packagingCode) {
        this.packagingCode = packagingCode;
    }

    public Dimension getPackageDimensions() {
        return dimensions;
    }

    public void setPackageDimensions(Dimension dimensions) throws ShippingException {
        this.dimensions = dimensions;

        if(!meetsDimensionalRequirements()) {
            this.dimensions = null;
            throw new ShippingException("This package's dimensions exceed limits.");
        }
    }

    public Weight getPackageWeight() {
        return weight;
    }

    public void setPackageWeight(Weight weight) throws ShippingException {
        this.weight = weight;

        if(!meetsWeightRequirements()) {
            this.weight = null;
            throw new ShippingException("This package's weight exceeds limits.");
        }
    }


    public abstract boolean meetsWeightRequirements();

    public abstract boolean meetsDimensionalRequirements();
}
然后我有一些类扩展了这个抽象类,如下所示:

public class WeightBasedPackage extends Package {

    public boolean meetsWeightRequirements() {
        Weight weight = this.getPackageWeight();
        boolean meetsRequirements = false;

        if(weight != null) {
            meetsRequirements = (weight.getWeight() > 0);
        }

        return meetsRequirements;
    }

    public boolean meetsDimensionalRequirements() {
        return true;
    }
}
我有另一个对象(
ShipRequest
),它维护一个包列表(
List
)。我还有一个服务(例如
WeightBasedPackageShipService
),它使用这个对象并可以访问这个包列表。这个实现工作得很好,因为服务并不真正关心它是什么类型的包。包之间唯一的区别是它们实现抽象方法的方式

这就是问题所在。我创建了一个新类:

public class OrderQuantityPackage extends Package {

    int quantity;

    public OrderQuantityPackage() {
        super();
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public int getQuantity() {
        return this.quantity;
    }

    public boolean meetsWeightRequirements() {
        return true;
    }

    public boolean meetsDimensionalRequirements() {
        return true;
    }
}
它有一个
数量
字段。我需要在服务中访问此字段(
OrderQuantityPackageShipService
)。然而,由于它是
Package
类型,所以我必须将其转换(看起来有点笨拙)

我的问题是,如何更好地实现这一点(这样我就不必强制转换)并确保类型安全(这样,如果您使用的是
OrderQuantityPackageShipService
,那么包的类型必须是
OrderQuantityPackage
)。我曾考虑过使用泛型,但对于我正在尝试做的事情来说似乎有点困难(
ShipRequest
有一系列其他属性,根据包的类型对其进行泛型似乎很奇怪)


谢谢。

也许您应该创建一个抽象服务,并扩展它以处理不同类型的包。您可以将处理方法抽象化,让每种服务都知道如何处理相应的包。如果您不想混合不同类型的包,那么这可能会起作用。

也许您应该创建一个抽象服务,并扩展它以处理不同类型的包。您可以将处理方法抽象化,让每种服务都知道如何处理相应的包。如果您不想混合不同类型的包,那么这可能会起作用。

简短回答:依赖倒置

您有一个OrderQuantityPackageShipService类,该类需要它处理的对象中的某些功能。因此OrderQuantityPackageShipService应该是指定这些需求的服务。通常,这是通过一个接口完成的。如果它非常特定于服务,则创建嵌套接口。即:

class OrderQuantityPackageShipService {
    //...
    interface QuantityPackage {
        int getQuantity();
        // ...
    }
}
如果其他服务可以以一致的方式使用它,请在OrderQuantityPackageShipService类之外定义它


然后让某些包实现该接口…

简短回答:依赖项反转

您有一个OrderQuantityPackageShipService类,该类需要它处理的对象中的某些功能。因此OrderQuantityPackageShipService应该是指定这些需求的服务。通常,这是通过一个接口完成的。如果它非常特定于服务,则创建嵌套接口。即:

class OrderQuantityPackageShipService {
    //...
    interface QuantityPackage {
        int getQuantity();
        // ...
    }
}
如果其他服务可以以一致的方式使用它,请在OrderQuantityPackageShipService类之外定义它


然后让某些包实现该接口…

我能想到的一件事是,为什么需要访问类
OrderQuantityPackageShipService
中的
quantity
属性?在我看来,类
包的每个属性都有一个getter和setter。真的需要这些能手和二传手吗?为所有这些属性设置getter/setter并不适合封装


您是否可以考虑在
类中提供在更高级别上运行且不公开内部属性的公共方法?这不是很有帮助吗?

我能想到的一件事是,为什么需要访问类
OrderQuantityPackageShipService
中的
quantity
属性?在我看来,类
包的每个属性都有一个getter和setter。真的需要这些能手和二传手吗?为所有这些属性设置getter/setter并不适合封装

public abstract class Package {
    protected String description;  // These shouldn't be private fields instead of protected?
    protected String packagingCode; // Nah, I don't think so, otherwise how could I store a value into the Quantity field? =P 
    protected Dimension dimensions;  
    protected Weight weight;  
    protected int quantity;

    // Constructors, getters and setters...

    public virtual int getQuantity {
        throw new NotImplementedException();
    }

    public virtual int setQuantity(int quantity) {
        throw new NotImplementedException();
    }
}

public final class OrderQuantityPackage extends Package {
    public override int getQuantity {
        return super.quantity;
    }

    public override void setQuantity(int quantity) {
        super.quantity = quantity;
    }
}
您是否可以考虑在
类中提供在更高级别上运行且不公开内部属性的公共方法?那不会有帮助吗

public abstract class Package {
    protected String description;  // These shouldn't be private fields instead of protected?
    protected String packagingCode; // Nah, I don't think so, otherwise how could I store a value into the Quantity field? =P 
    protected Dimension dimensions;  
    protected Weight weight;  
    protected int quantity;

    // Constructors, getters and setters...

    public virtual int getQuantity {
        throw new NotImplementedException();
    }

    public virtual int setQuantity(int quantity) {
        throw new NotImplementedException();
    }
}

public final class OrderQuantityPackage extends Package {
    public override int getQuantity {
        return super.quantity;
    }

    public override void setQuantity(int quantity) {
        super.quantity = quantity;
    }
}
虽然我不能完全确定语法,也不能完全确定NotImplementedException,但我希望您能理解。因此,任何需要或需要数量的包派生类都可以通过重写quantity属性的getter和setter来实现

在不需要数量的地方不应该抛出异常,也不应该调用它,因此不应该抛出异常。此外,它还证明了您的模型只在时机成熟时执行所需的操作

除此之外,OrderQuantityShipService不需要OrderQuantityPackage中的Weight属性,正如Vivin所写的,您可以访问Weight

否则,您的服务中的一个简单强制转换就可以做到这一点。使用铸造并不是一种肮脏的方式。例如,必须将事件处理程序中的发送方对象强制转换为希望检查名称、状态或其他属性值的适当控件类型!最普通的类然后被传递到事件,并且必须铸造。。。这个,那个不是我说的选择这种方式,这些是软件工程师

EDITVivin,在JAVA中如何从一种数据类型转换到另一种数据类型,是否与在C/C++/C#中一样

虽然我不能完全确定语法,也不能完全确定NotImplementedException,但我希望您能理解。因此,任何需要或需要数量的包派生类都可以通过重写quantity属性的getter和setter来实现

对于不需要数量的地方,不应该抛出异常,它不应该得到c