class A{
 public String f(D obj){return ("A and D");}
 public String f(A obj){return ("A and A");}
}
class B extends A{
 public String f(B obj){return ("B and B");}
 public String f(A obj){return ("B and A");}
}
class C extends B{}
class D extends B{}public class test{
 public static void main(String args[]){
  A a1 = new A();
  A a2 = new B();
  B b = new B();
  C c = new C();
  D d = new D();
  System.out.println(a1.f(b));   //A and A
  System.out.println(a1.f(c));   //A and A
  System.out.println(a1.f(d));   //A and D
  System.out.println(a2.f(b)); //B and A
  System.out.println(a2.f(c)); //B and A
  System.out.println(a2.f(d)); //A and D
  System.out.println(b.f(b));    //B and B
  System.out.println(b.f(c));    //B and B
  System.out.println(b.f(d)); //A and D
 }
}谁能详细的说下结果为什么会是这样啊?

解决方案 »

  1.   

    System.out.println(a1.f(b));   //A and A
      System.out.println(a1.f(c));   //A and A
      System.out.println(a1.f(d));   //A and D
    首先他调用的是类A的方法.这应该不用解释了.其次BC丙个对像已经转成了类A的对像.所以输出A and A.
    public String f(A obj){return ("B and A");}接受一个类D的对像.当然就输出A and D
    下面的应该不用解释了.一句话.多态!当然这是个人理解!俺也是个菜鸟滴!呵
      

  2.   

    public static void main(String args[]) {
    A a1 = new A();
    A a2 = new B();//a2是类A的对象,可以调用类B中覆写类A中和类A本身的方法,
                    //a2是使用上传的方法声明的
    B b = new B();
    C c = new C();
    D d = new D();
    System.out.println(a1.f(b)); //A and A,A是父类,只能调用A类中的方法
    System.out.println(a1.f(c)); //A and A,对象c是类A的孙子C的对象,所以可以向上转型为A的对象
    System.out.println(a1.f(d)); //A and D,对象d是D类的对象,所以可以调用类A的f(D obj)方法
    System.out.println(a2.f(b)); //B and A,
    System.out.println(a2.f(c)); //B and A
    System.out.println(a2.f(d)); //A and D,因为类B中没有覆写f(D obj)的方法,所以调用的是类A中的方法
    System.out.println(b.f(b)); //B and B,b是类B的对象,所以调用类B的方法f(B obj)
    System.out.println(b.f(c)); //B and B,因为c是类B的子类C的对象,而且类B中没有f(C obj)方法,所以调用类B的f(B obj)
    System.out.println(b.f(d)); //A and D,因为类B没有f(D obj)的方法,而且d是类A的子类的子类D的对象,所以调用的是类A的方法
    }
    其中System.out.println(a2.f(b)); //B and A,
    System.out.println(a2.f(c)); //B and A
    这两句没明白,哪位高手解释一下啊,谢谢
      

  3.   

    System.out.println(a2.f(b)); //B and A
    a2是A对象,但用B初试化的
    所以传进去一个B对象,在A的方法里找到
    public String f(A obj){return ("A and A");}
    因为是被B初试化的,所以方法体要用B里面覆盖的方法
    public String f(A obj){return ("B and A");}
    所以就得到结果了楼上仁兄说的对,先在自己的里面找,然后再到父类找,但要注意的是你如果是用子类初试话的话,那方法体就给覆盖了,
      

  4.   

    System.out.println(a2.f(b)); //B and A,
    System.out.println(a2.f(c)); //B and A
    这两句一样的,就是上面我说的原因,查找方法是在A里面查找的,但运行的操作是B里面覆盖的,所以是不会出现B and B的,只有//B and A,
      

  5.   

    有没有高手解释一下对象查找父类和调用其中方法的规则和顺序,比如最后一句
    System.out.println(b.f(d)); //A and D同样,D is a B is a A,但为什么执行的不是B类中的public String f(B obj){return ("B and B");}方法,而是A类中的public String f(D obj){return ("A and D");}方法,是不是方法调用的顺序上的规则所致?先谢过了。
      

  6.   

    obj.func(param);
    根据引用obj类型和参数param类型来匹配:
    1)先在obj引用对应的类中找(A a2 = new B();是在A中找的)有没有参数跟param类型相同的方法,有调用;
    2)没有,看有没有参数跟param类型的直接父类相匹配的,有则调用;依次上溯到Object类
    3)仍没有匹配的,在引用obj的直接父类的方法中按1)2)的次序仿效匹配参数类型.没有匹配到的话再往上一层父类方法中找,直到上溯到Object类.
    4)仍没有匹配的,会报错.这样可以明白除了第4,5个以外的调用了吧.
    这两个例外的情况就是多态(追究概念的话上面属于继承~)
    因为a2实际是B类型,而B继承A,A、B中都有f(A obj)方法,它会调用B的f方法而不是A的.
      

  7.   

    System.out.println(b.f(d)); //A and D是因为b对象里面有一个可以直接调用的方法
    public String f(D obj){return ("A and D");}既然能直接调用就不会继续去转化传进来的对象了
    如果你把这个方法去掉,那结果就不会是这样了,你可以改一下再试试看
      

  8.   

    匹配的时候是参数优先的.
    有一个典型的例子就是
    接口 java.lang.Comparable中的boolean equals(Object obj)方法
    不要误写为:
    boolean equals(MyClass obj)
    这样就不是多态了~
      

  9.   

    如果是参数优先,那为什么呢?
    System.out.println(a2.f(b)); //B and A,
    System.out.println(a2.f(c)); //B and A
      

  10.   

    sandflying(飞沙) ( ) 信誉:100    Blog 
    =========================================恩,这个我已经明白了,class B 里已经继承了public String f(D obj){return ("A and D");},所以System.out.println(b.f(d)); //A and D可以直接在class B里找到该方法.
      

  11.   

    比如:
    class A
    {
         public String f(C obj){return ("A and C");}
    };class B extends A
    {
    };class C extends B
    {
    };class D extends C
    {
        public String f(B obj){return ("D and B");}
    };
    class Test 
    {
        public static void main(String[] args) 
        {
            D d=new D();
            System.out.println(d.f(d)); //调用的会是A的方法~
        }
    }
      

  12.   

    System.out.println(a2.f(b)); //它的结果为什么不是B and B呢?
    a2是类B的对象,它覆写了类A的方法,b是类B的对象,所以...
      

  13.   

    changyuming(常) ( ) 信誉:97    Blog  2006-12-15 13:12:11  得分: 0   
       System.out.println(a2.f(b)); //它的结果为什么不是B and B呢?
    a2是类B的对象,它覆写了类A的方法,b是类B的对象,所以...
      =========
    因为a2是A类型的呀(虽然它实际上是B的实例)
    比如说B中有个方法叫funcB()但A中没有,此时:
    A a = new B();
    a.funcB();//这么写会报错的!!调用方法它看引用是什么类型
     
      

  14.   

    class A{  //包含2个方法A.f(D obj)、A.f(A obj)
     public String f(D obj){return ("A and D");}
     public String f(A obj){return ("A and A");}
    }
    class B extends A{  //包含3个方法,A.f(D obj)、A|B.f(A obj)(已覆盖)、B.f(B obj)
     public String f(B obj){return ("B and B");}
     public String f(A obj){return ("B and A");}
    }
    class C extends B{}  //包含3个方法
    class D extends B{}  //包含3个方法class test{
     A a1 = new A();
    //a1有两个方法A.f(D obj)、A.f(A obj)
     A a2 = new B();
    //a2只有两个方法A.f(D obj)、A|B.f(A obj)(已覆盖),B.f(B obj)对于a2不可见
     B b = new B();
    //b有三个方A.f(D obj)、A|B.f(A obj)、B.f(B obj)
     C c = new C();
     D d = new D();
     System.out.println(a1.f(b));
    //a1没有这种参数形式,调用a1.f((super)b),就是调用a1.f((A)b)---->"A and A"
     System.out.println(a1.f(c));
    //a1没有这种参数形式,调用a1.f((super)((super)b)),就是调用a1.f((A)b)---->"A and A"
     System.out.println(a1.f(d));
    //调用a1.f(d)---->"A and D"
     System.out.println(a2.f(b));
    //由于B.f(B obj)对于a2不可见,a2没有这种参数形式,调用a2.f((super)b),就是调用a2.f((A)b)(已覆盖)---->"B and A"
     System.out.println(a2.f(c));
    //由于B.f(B obj)对于a2不可见,a2没有这种参数形式,调用a2.f((super)((super)b)),就是调用a2.f((A)b)(已覆盖)---->"B and A"
     System.out.println(a2.f(d));
    //调用a2.f(d)---->"A and D"
     System.out.println(b.f(b));
    //调用b.f(b)---->"B and B"
     System.out.println(b.f(c));
    //b没有这种参数形式,调用b.f((super)c),就是调用b.f((B)c)---->"B and B"
     System.out.println(b.f(d));
    //调用b.f(d)---->"A and D"
    }
      

  15.   

    #include <iostream>
    using namespace std;
    class D;
    class A
    {
    public:
    void f(A* a){
    cout<<"A and A"<<endl;
    }
    void f(D* d){
    cout<<"A and D"<<endl;
    }};class B :public A
    {
    public:
    void f(A* a){
    cout<<"B and A"<<endl;
    }
    void f(B* b){
    cout<<"B and B"<<endl;
    }
    };
    class C : public B{
    };
    class D:public B{
    };void main()
    {
    A *a1 = new A();
    A *a2 = new B();
    B *b  = new B();
    C *c  = new C();
    D *d  = new D(); a1->f(b);
    a1->f(c);
    a1->f(d);
    a2->f(b);
    a2->f(c);
    a2->f(d);
    b->f(b);
    b->f(c);
    b->f(d); delete a1;
    delete a2;
    delete b;
    delete c;
    delete d;
    }
    我在VC6下执行,结果却是:
    A and A
    A and A
    A and D
    A and A
    A and A
    A and D
    B and B
    B and B
    B and B
    各位帮忙解释一下哈
      

  16.   

    1.把A::f(A* a)声明为virtual.
    但是b->f(d) 怎么不调用A::f(D* d)呢?也就是最后那个应该是A and D才对啊。
    请教。
      

  17.   

    我在派生类里重载父类的函数,比如
    class A
    {
    public: void f(int){
    cout<<"A and int"<<endl;
    }
    };class B :public A
    {
    public:
    void f(double ){
    cout<<"B and double"<<endl;
    }
    };
    然后我这么调用:
    B *b  = new B();
    int i = 5;
    b->f(i);
    输出却是 B and double? 为什么呢。