Java 关于基类和派生类的实现问题
我有一个关于实施这一点的最佳方式的问题。我将描述我当前的实现,以及我是如何将自己陷入困境的: 我有一个名为Package的抽象类: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
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