首先,我将提供我的示例代码。
public class Shape {
public String colour;
public Shape(String colour) {
this.colour = colour;
}
}
public class Car {
public String colour;
public Car (String colour) {
this.colour = colour;
}
}
public class Colour {
public static String getColour(Object item) {
return item.**colour**;
}
}
我已经阅读了与此相关的其他问题,但我似乎无法理解。我发现他们的原始代码对我来说太复杂了。所以我试着尽可能简单地编写代码。无论如何,我希望getColour同时接受Shape和Car对象。如果我像我在我的例子中那样使用Object,那么" color"以粗体显示为错误。我得到的错误是"颜色无法解析或不是字段"。怎么了?
另外,我听说很多"静态方法都很糟糕"这是一个坏的情况吗?因为我发现如果我不能使它静止,那么我需要在Shape和Car类中复制getColour方法。如果我应该避免静态方法,那么请建议另一种方法来做到这一点。
答案 0 :(得分:3)
您正在寻找的是interfaces:
的概念public interface Colourable {
String getColour();
void setColour(String colour);
}
您应该修改Shape
和Car
类:
public class Shape implements Colourable {
public Shape(String colour) {
this.colour = colour;
}
private String colour;
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
}
(请注意,我已将colour
字段设为私有;这是常见操作,称为encapsulation
)
然后,您可以将静态方法定义为
public static String getColour(Colourable item) {
return item.getColour();
}
静态方法肯定不错,但在这种情况下,方法本身有点多余,因为如果你已经有Colourable
,你知道你可以调用.getColour()
来获取它的颜色。更有用的是方法
public static boolean isRed(Colourable item) {
return "red".equals(item.getColour());
}
答案 1 :(得分:1)
好像你试图使用duck typing,这不是Java的工作方式。
最简单的做法是恕我直言,定义一个界面来处理颜色。 E.g:
public interface Colourful {
public String getColour();
}
public class Shape implements Colorful {
private String colour;
public Shape(String colour) {
this.colour = colour;
}
@Override
public String getColour() {
return colour;
}
}
public class Car {
private String colour;
public Car (String colour) {
this.colour = colour;
}
@Override
public String getColour() {
return colour;
}
}
或者,如果您不想更改Shape
和Car
,则可以使用反射来提取colour
字段,但这通常被视为一个坏主意,并且你可能最好不要使用它:
public static String getColour(Object o) {
Field colourField;
try {
colourField = o.getClass().getField("colour");
} catch (NoSuchFieldException e) {
// No such field
return null;
}
Object colourValue;
try {
colourValue = colourField.get(o);
} catch (IllegalAccessException e) {
// The field isn't public
return null;
}
if (!(colourValue instanceof String)) {
// The field isn't a String
return null;
}
return (String) colourValue;
}
答案 2 :(得分:1)
你可以"统一" Shape
和Car
。有两种通用方法:
让我们看看两者。
继承:当一个类Porsche
继承(或者,在Java语法中,extends
)一个类Car
时,你建立一个"是-a"关系。在这种情况下:Porsche
是-a Car
。现在,当您使用对象引用时,魔法就会起作用。你现在可以这样写:
Car c = new Porsche();
由于Porsche
包含所有内容,Car
包含(加上一些内容),您可以看到Porsche
为Car
(每个Porsche
}是Car
,但不是每个Car
都是Porsche
)。仔细阅读我的最后一句,很明显,以下内容不起作用,实际上会产生编译错误:
Porsche p = new Car();
您现在可以做的是编写一个方法,该方法需要Car
并传入Porsche
(因为每个Porsche
都是Car
)。
回到你的榜样。为了实现这一点,您可以为Shape
和Car
定义一个公共父类,让我们称之为Colourable
并为其指定方法public Colour getColour()
。然后,您只需将getColour(Object item)
方法更改为getColour(Colourable c)
。
记得我说的关于" is-a"关系?问问自己:每个Shape
是Colourable
吗?每个Car
是Colourable
吗?为什么Car
和Shape
都在同一个存储区(Colourable
)中?如果Car
已经有父类,例如,该做什么Vehicle
?该解决方案不是最佳的。
接口:这是接口发挥作用的地方。接口保证存在某些方法。您可以简单地将Colourable
编写为包含方法Colourable
的接口,而不是定义公共父类public Colour getColour()
。现在Shape
和Car
可以implements
此界面。这会强制您在两个类中实现此方法。美:你可以像类一样使用接口。这意味着您getColour(Colourable c)
的实施不需要改变。
有关详细信息,请阅读Inheritance和Interfaces上提供的教程。
答案 3 :(得分:0)
抛出错误的原因是Object
没有颜色字段。我不推荐它,但是如果你想继续这个设计,你可以创建一个名为ShapeCarParent的类(在这种情况下使用,因为我看不到两者之间没有明确的关系)并让两个类都继承自,然后更改getColour,如下所示:
public class ShapeCarParent{
public String colour;
}
public class Car extends ShapeCarParent
public class Shape extends ShapeCarParent
public class Colour {
public static String getColour(ShapeCarParent item) {
return item.colour;
}
}
这仍然是非常糟糕的风格,所以你也可以使用一个接口然后在每个类中实现。
public interface ColorProperties{
public String getColour();
}
public class Car implements ColorProperites{
public String getColour() {
return colour;
}
}
public class Shape implements ColorProperites{
public String getColour() {
return colour;
}
}
希望这有帮助。