【问题标题】:type casting when objects are of interface references in Java当对象是Java中的接口引用时的类型转换
【发布时间】:2014-02-28 22:29:59
【问题描述】:

我熟悉inheritance model中的type casting

SuperClass and SubClass为父子类;

SuperClass superClass = new SubClass(); -- 这里实例化的objectsubclass object; 但它的reference typeSuperClass;只有SuperClass 中的methods 可以在subclass object 上调用;不能调用在subclass 中不是inherited/overridden 的任何methods(即subclass 中的任何唯一methods)。

如果SuperClass is an interfaceSubClass implements it,我观察到与上述相同的行为。只有在SuperClass interface 中声明的那些方法才能在SubClass 对象上调用。我的理解正确吗?但是对于一些casting,我可以调用不属于接口的methods,我在下面的示例代码中观察到了这一点;

我对它的工作原理做了一些 cmets; 但我想知道这是否有意义,或者我的解释是否错误;

class Animals {

     public void bark(){
         System.out.println("animal is barking");
     }

}

 interface catIF {
     public void catting();

 }

interface dogIF {
    public void dogging();
 }

class Dog extends Animals implements dogIF {

    public void bark(){
        System.out.println("dog is barking");
    }


    public void dogging() {
        System.out.println("dogging");

    }

}

class Cat extends Animals implements catIF {

    public void bark(){
        System.out.println("cat is barking");
    }


    public void catting() {
        System.out.println("catting");

    }

}

public class Animal {

    public static void main(String[] args){
        dogIF dog = new Dog();
        //dog.bark(); this fails
        //This method actually actually exists;
        //but it is not available or hidden because dogIF reference
        //limits its availability; (this is similar to inheritance)

        Dog dog2 = new Dog();
        dog2.bark();
        ////prints dog is barking

        Animals an =(Animals) dog;
        an.bark();
        //prints dog is barking
        //by casting we mean, treat the dog as an animals reference
        //but the object itself is a dog.
        //call the bark() method of dog
        //but dog did not have this method in the beginning (see first line
        // in main - when instantiated with interface type)
        }
     }

【问题讨论】:

  • dogIF#bark() 不存在,所以你是对的。方法调用在编译时根据引用的声明类型进行解析。
  • 是的,你的理解完全没问题。
  • 继承如果接口在 Java 中有点不稳定——我不确定是否有人真正理解它。 (我理解它足够长的时间来实现checkcast,但规则太神秘了,我早就忘记了。)
  • 但是要理解的一件事是,当您进行显式转换(例如(Animals))时,编译器会相信您所说的对象是指定的类型。在幕后,checkcast 字节码可确保您所说的是真的,但编译器不知道checkcast 是成功还是失败。
  • 强制转换在生效前检查对象是否实现了新类型,如果没有则抛出ClassCastException。因此,CatDog 扩展/实现 Animals 并且可以转换为 Animals,但它们彼此之间没有超/子类关系,因此您不能将一个转换为另一个。虽然您可以拥有一个扩展Cat 并实现dogIF 的对象,但如果您想描述一只猫与狗共享后一种行为……就像我的一样,它有时会取回一个球.

标签: java inheritance interface casting


【解决方案1】:

接口的继承实际上并不“不稳定”或复杂。它们的行为与抽象类完全一样,除了您以不同的方式引用它们(实现而不是扩展),并且您可以继承任意数量的接口,但只能拥有一个超类(抽象与否)。

与其他继承一样:如果您只知道一个对象实现了一个接口,那么您只能通过该接口访问它。如果您知道它实现了另一个接口,或特定的超类,或者是特定类的实例,那么您可以将其强制转换为这些接口,并通过这些接口的公开成员访问它。

所以,是的:如果您的程序只知道该对象是Animals 的一个实例,那么您所能做的就是调用动物上声明的内容。这意味着bark() 加上它从Object 继承的任何方法(因为一切都是直接或间接的Object,即使没有明确说明)。

如果您的程序知道该对象是 dogIFcatIF 的实现——因为变量类型表明它是,或者因为你已经成功地将它类型转换为这些接口之一——你也可以调用这些接口声明的方法。顺便说一句,接口的通常约定是将它们命名为类,使用 UppercasedFirstLetter... 因为在许多情况下,接口和类之间的区别对于使用它的人来说并不重要。

如果您的程序碰巧知道该对象是Dog,您可以调用它从AnimalsdogIF 继承的任何东西,或者直接由Dog 提供的任何东西。当然它实际上可能是Chihuahua(狗的子类),但没关系,子类将以“维护语义的正确方式”响应超类会响应的任何内容。 (也就是说,Chihuahua 可能会通过说“yip yip yip grr yip!”来回应bark(),但这种方法确实不应该导致它试图咬你的脚踝。)

希望对您有所帮助。真的没那么复杂。

【讨论】:

  • 变量类型和引用类型一样吗?关于你的句子If your program happens to know that the object is a Dog, you can call anything it inherits from either Animals or dogIF, or that is provided directly by Dog——只有当我声明Dog dog = new Dog(); but not Animals dog = new Dog() or dogIF dog = new Dog()时才有可能@
  • 1) Java 中的所有对象变量都是引用,所以是的。 (与对象的实际类型相反。) (2) 如果您知道该对象是 Dog -- 因为您创建了它,或者因为您从其他上下文中知道,或者因为您刚刚使用了 @987654337 @ 操作来检查这一点 - 您可以安全地将其类型转换为 Dog 并将其视为这样。我承认我的人手不足。
  • 考虑这个:dogIF dog = new Dog();对象是Dog object;但这是不允许的:(Dog)dog.bark()。我想我在这里有一些误解..
  • 不能保证任意的dogIF 可以转换为Dog——但这只是意味着如果对象不是它被转换为的实例,则转换将抛出 ClassCastException .如果它 Dog 的一个实例,则类型转换没有任何问题......尽管您可能需要小心确保您正在转换对象而不是结果。试试((Dog)dog).bark()
  • 您不必编写checkcast 后面的代码...并让它通过Sun 验收测试。有几个不明显的曲折。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 2019-12-12
  • 1970-01-01
相关资源
最近更新 更多