黑马程序员技术交流社区

标题: 关于多态的疑问 [打印本页]

作者: yangchao8907    时间: 2013-8-3 18:20
标题: 关于多态的疑问
  1. interface A
  2. {
  3. }

  4. class B implements A
  5. {
  6.         public String func()
  7.         {
  8.                 return "func";
  9.         }
  10. }

  11. class Demo3
  12. {
  13.         public static void main(String[] args)
  14.         {
  15.                 A a = new B();
  16.                 System.out.println(a.func());
  17.         }
  18. }
复制代码
为什么interface A中不定义func()方法,就编译失败?
请具体说说父类的引用指向子类的对象,这一类的问题的解决思路是什么?

作者: 肥猫    时间: 2013-8-3 19:19
你的变量a声明的是A类型的,多态的情况,编译看左边,运行看右边,所以你左边的A没有声明这个方法编译就通不过.
作者: 狐灵    时间: 2013-8-3 20:39
本帖最后由 狐灵 于 2013-8-3 20:50 编辑

因为   A a = new B();
这个说明你在用接口来接受实例化出来的对象。这样的话,你只能使用接口a提供的方法。但是你在定义接口a的时候没有定义任何方法,所以,编译的时候因为在接口类a中找不到相应的方法而报错。
你用哪个类型来接收,就只能用这个类中定义的方法。除非强制转型。比如你的代码改成这样就可以正常输出。
  1. interface A {
  2. }

  3. class B implements A {
  4.                 public String func() {
  5.                         return "func";
  6.                 }
  7. }

  8. class Demo3 {
  9.         public static void main(String[] args)  {
  10.                 A a = new B();
  11.                 System.out.println(((B) a).func());
  12.         }
  13. }
复制代码
接口和实现类之间不是extends那种继承关系,他们之间的关系是扩展,也就是实现类实现了接口。当然实现类本身也是一个类,所以也可以存在接口中没有的方法。这个方法属于实现类不属于接口。

336.JPG (10.26 KB, 下载次数: 29)

336.JPG

作者: 天地有我    时间: 2013-8-5 20:42
本帖最后由 天地有我 于 2013-8-5 20:44 编辑

interface A
{
}

class B implements A
{
        public String func()
        {
                return "func";
        }
}

class Demo3
{
        public static void main(String[] args)
        {
                    
                A a = new B();  // 这里存在隐式的类型转换,向上类型转换。(多态)
                B b = (B)a; //func()方法是Demo3中才有的,是子类扩展的方法。
                //System.out.println(a.func());
                System.out.println(b.func());
        }
}

多态:所谓多态,就是父类型的引用可以指向子类型的对象,或者接口类型
的引用可以指向实现该接口的类的实例。关于接口与实现接口的类之间的强
制类型转换方式与父类和子类之间的强制类型转换方式完全一样。

多态是一个子类型的应用指向父类型的对象。 方法的调用是取决于左边的类型
A a = new B();
虽然是一个B类型的引用(new B()) 但是这个应用类型指向的是一个A类型的变量 a,   func()方法是B中才有的,根据多态原理父类有的子类可以继承
父类没有的,子类可以扩展,这里的func()方法就属于子类扩展的方法,所以不能用A类型的变量a来调用它,因为接口A中没有这个方法,
所以如果当一个子类型的应用指向父类型的变量而父类型有没有子类型中的所有方法的时候,这时候如果要掉用父类型中没有的方法,就不能用多态了,必须将父类型的变量强制转换成子类型的变量。
所以这里必须要向下类型转换(就是将父类型的对象转换为子类型的对象)才行。向下类型转换,不能隐式转换,只能强制类型转换,所以要将A向下强制转换为B类型,转换过后就能调用B类中的func()方法了。
作者: 牛海亮    时间: 2013-8-6 10:04
就第一问做如下解答:
我觉得你对接口的理解有一点欠缺,定义一个接口就是定义了一种规则,而一个类实现这一个接口其实就是向用户表明我符合这个接口中的规则。接口A中什么都不定义,就是说A中什么规则也没有,B想去实现A,但又不知道要实现A接口的什么,所以编译器就通不过了。
假如说在A接口中定义为:
  1. public interface A {
  2.         public String func();
  3. }
复制代码
那么B类实现A的时候就知道了,我要实现接口A 我也得有一个func方法,这样就才符合接口A的规则。
所以A接口这样定义后编译器在编译的时候就能明白了,也就是编译能通过了。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2