繁体   English   中英

Java:介面

[英]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)。 现在,一个RectanglePlusRelatable ,但是逆不一定成立。 此处的转换确保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 (具有isLargerThangetArea的接口)的CircleHexagonRectangle等类,并且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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM