[英]Java: Interface
我一直在阅读有关Java接口的信息。 总的来说,我理解这个概念,除了一个问题。 在http://goo.gl/l5r69(docs.oracle )中,在笔记中写道,我们可以类型转换接口和实现该接口的类。 那是
public interface Relatable {
public int isLargerThan (Relatable other) ;
}
public class RectanglePlus implements Relatable {
public int width = 0;
public int height = 0;
public Point origin;
// four constructors
// ...
// a method for computing the area of the rectangle
public int getArea() {
return width * height;
}
// a method required to implement the Relatable interface
public int isLargerThan(Relatable other) {
RectanglePlus otherRect = (RectanglePlus) other;
if (this.getArea() < otherRect.getArea()) {
return -1;
} else if (this.getArea () > otherRect.getArea()) {
return 1;
} else {
return 0;
}
}
}
如何将otherRect(这是一个接口)强制转换为RectanglePlus。 令人困惑的是,RectanglePlus是具有变量的类 ,该变量在作为接口的otherRect中不存在
您的界面非常类似于Comparable ,(您确定Comparable并不是您想要的吗?),所以也许您应该向其添加通用名称:
public interface Relatable<T extends Relatable> {
public int isLargerThan(T t);
}
然后您的课程将开始为:
public class RectanglePlus implements Relatable<RectanglePlus> {...
因此,您的RectanglePlus实例将仅与其他RectanglesPlus元素进行比较。
如果这不符合您的需求,那么您必须选择在比较两个不同的类时将发生的情况:
public class RectanglePlus implements Relatable {
public int width = 0;
public int height = 0;
public Point origin;
public int getArea() {
return width * height;
}
public int isLargerThan(Relatable other) {
if (!(other instanceof RectanglePlus)) {
return 1; // I'm bigger than any other class!
}
RectanglePlus otherRect =(RectanglePlus)other;
return this.getArea() - otherRect.getArea();
}
}
或者,第三个选择是,您可以在界面中添加另一种方法以获得对象的可测量且可实现的值。 然后,如果您使用的是Java 8,则可以向isLargerThan添加默认实现:
public interface Relatable<T extends Relatable> {
public default int isLargerThan(T t) {
return this.getRelatableValue - t.getRelatableValue();
}
public int getRelatableValue();
}
我必须承认,您显示的Java文档中的示例简直是糟糕且令人困惑。 这很糟糕,因为它包含不安全的层次结构 。 强制转换(从实现类到接口/超类)始终是安全的,但应尽可能避免强制转换。
理想情况下, Relatable
接口还应该包含getArea()
方法:
public interface Relatable {
public int isLargerThan(Relatable other);
public int getArea();
}
现在,您不需要丑陋的演员表,只需:
public int isLargerThan(Relatable other) {
if (this.getArea() < other.getArea()) {
return -1;
} else if (this.getArea () > other.getArea()) {
return 1;
} else {
return 0;
}
}
足够。 我还认为isLargerThan(Relatable other)
是一个不好的名字(就什么而言更大)。 它可能应该类似于hasBiggerArea(Relatable other)
类的东西,以便它解释我们实际上正在比较的内容(只有“较大”才是比较时尚的)。
在方法声明public int isLargerThan(Relatable other){...}
,参数other
被声明为对该对象的引用,该对象的类实现了Relatable
接口。
在方法主体中,表达式(RectanglePlus)other
表示检查对象是否为RectanglePlus
类或该类的子类(如果不是,则抛出ClassCastException)。 现在,一个RectanglePlus
是Relatable
,但是逆不一定成立。 此处的转换确保other
将是RectanglePlus
; 如果不是这样,将不会执行进一步的指令,因为将引发异常。
如果T2是类C的超类或T2 == C的超级接口,我们可以将类型T1的变量(接口或类)中存储的任何对象(类C)转换为类型T2的变量,否则ClassCastException被抛出。
因此,在您的情况下,如果将Foo类实现Relatable的对象obj传递给isLargerThan方法,则它将抛出ClassCastException ,因为obj的 Foo类不是RectanglePlus的超类。
在其他答案中没有涉及的一个方面是Oracle文档中的示例存在一个明显的问题:如果Relatable
仅旨在类似于Comparable
,则需要对形状进行专门化处理,以便避免在isLargerThan
方法中进行isLargerThan
。 例如,也许有一个名为RelatableShape
的接口,该接口本身扩展了Relatable
,并提供了getArea()
方法。 然后,您可以具有实现RelatableShape
(具有isLargerThan
和getArea
的接口)的Circle
, Hexagon
, Rectangle
等类,并且isLargerThan()
方法无需将其参数isLargerThan()
转换为特定的具体类(因为该参数可以是保证实现RelatableShape
,并且getArea()
将始终可用)。
因此,尽管Oracle文档显示的是Java的有效内容 ,但由于设计不良 ,它也显示了必要的内容。 记住这一点。 在实际代码中,铸造几乎从来没有必要。
你的方法很简单
public int isLargerThan(Relatable other)
只是要求一个实现Relatable的参数。 它可以是实现Relatable的任何类的对象。 只要有类似的东西
public class SomeName implements Relatable { /* Implementation */ }
在类中,您可以将该类的对象视为可关联对象。
但这并不意味着这些对象不是自己的类型。 如果您有以下课程
public class Square implements Relatable {
public int isLargerThan(Relatable other) {
// Implementation
}
// Square specific implementation
}
和
public class Rectangle implements Relatable {
public int isLargerThan(Relatable other) {
// implmentation
}
// Rectangle specific implemenation
}
您可以像这样调用接口方法:
/* ... */
public static int check(Relatable a, Relatable b) {
return a.isLargerThan(b);
}
/* ... */
Square s = new Square();
Rectangle r = new Rectangle();
System.out.println("Check: " + check(s, r));
注意:因为几个不同的类可以实现Relatable,所以必须检查isLargerThan的参数类型,否则会遇到类型转换异常。
也许您可以在Relatable中指定类似的内容
public int getSize();
比您可以像这样编写isLargeThan方法:
public int isLargerThan(Relatable other) {
if (this.getSize() < other.getSize())
return -1;
else if (this.getSize() > other.getSize())
return 1;
else
return 0;
}
这样就不需要类型转换了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.