第一个程序
class C{
void callme(){System.out.println("abd");}
}
public class q extends C{void metoo(){
System.out.println("inside");}
public static void main(String arg[]){
C c=new q();
c.metoo();
}
}
这个程序为什么不能编译
出错提示是 q.java:8 找不到符号
符号: 方法 metoo( )
位置: 类C
其中C c=new q()  是生成了一个类q的实例,并把它的引用返回到C型变量c中 但为什么编译就不能通过 请先看第2个程序 因为这个程序编译不能通过的话我觉得和第2个程序的运行结果相矛盾第2个程序
class C{
void callme(){System.out.println("abd");}
void metoo(){
System.out.println("inside abc");}
}
public class q extends C{void metoo(){
System.out.println("inside");}
public static void main(String arg[]){
C c=new q();
c.metoo();
}
}
运行的结果是inside  为什么运行结果不是inside abc呢 这样不是和第1个程序矛盾吗 请哪位高手详细解释一下

解决方案 »

  1.   

    楼主大概还不知道什么叫“重写(Overriding)”和“多态(Polymorphism)”吧?参考一下相关的知识就明白了。
      

  2.   

    顶楼上,第一个程序:多态不是这样用的。第二个程序:当你有更多的类继承自class C的时候,你自然就知道为结果会是 “inside”了
      

  3.   

    class C{
    void callme(){
    System.out.println("abd");

    void metoo(){
    }
    }
    public class q extends C{
             //overriding 父类方法  
    void metoo(){
    System.out.println("inside");
    }
    public static void main(String arg[]){
    C c=new q();     //实际上c还是属于q类的一个实例
    c.callme();  //c没有自己的callme()方法,callme()方法是从父类继承的
    c.metoo();
    }
    }
    输出结果是
    abd
    inside
      

  4.   

    第一个程序 既然c是q的一个实例  而metoo()是类q中的一个方法 那c.metoo()应该可以编译通过 结果是inside 为什么要编译不能通过呢
      

  5.   

    第一个例子,虽然new q()是q的一个实例,但c是一个C类型的变量,因些,你把new q()赋给c的时候,执行了向上转型,c已经被看作是一个C的实例了,这样,C类中没有的接口都被屏蔽了,因此,也就不能调用q类中有的而C类中没有的metoo()方法了。每二个例子是一个常见的多态的例子。
      

  6.   

    这样说的话 有一个地方我就更不能理解了  看下面这个程序
    abstract void class C{
    abstract void callme();
    void metoo(){
    System.out.println("inside abc");}
    }
    public class q extends C{void callme(){
    System.out.println("inside");}
    public static void main(String arg[]){
    C c=new q();
    c.metoo();
    c.callme();
    }
    }
    如果说c被看做是一个C的实例的话 但是abstract类是不能实例化的啊 这怎么解释啊
      

  7.   

    楼主记好:new q()是q的一个实例,但c是一个C类型的变量,因些,你把new q()赋给c的时候,执行了向上转型,“c已经被看作是一个C的实例了”,c只是一个引用q实例的变量,q实例的确存在,但是C中没有metoo方法,执行当然出错
      

  8.   

    这样说的话 有一个地方我就更不能理解了  看下面这个程序
    abstract void class C{
    abstract void callme();
    void metoo(){
    System.out.println("inside abc");}
    }
    public class q extends C{void callme(){
    System.out.println("inside");}
    public static void main(String arg[]){
    C c=new q();
    c.metoo();
    c.callme();
    }
    }
    如果说c被看做是一个C的实例的话 但是abstract类是不能实例化的啊 这怎么解释啊还有所说的向上转型,是不是说子类强制转换成父类了
      

  9.   

    abstract类是不能被实例化的,但是可以声明abstract类的引用,这个引用可以指向其子类的实例对象;
    向上转型是指:对于子类的对象可以用父类引用来指向,虽然实际生成的对象是子类的对象,但是通过父类的引用来指向的,所以通过这个父类的引用只能访问父类中定义的方法;同理,实现接口的类与接口的向上转型与此类似;
      

  10.   

    方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。第一个程序没有完成重写,是错误的,只有实现了重写,才能编译通过。第二个程序完成了重写,把一个父类的对象实例化为一个子类对象,调用被重写了的方法,当然要访问子类里的metoo()了,第三个程序,抽象类和抽象方法就是用来被实例化的,类q实现了它,而且在main里抽象类C被实例化成了一个非抽象类的对象,这就是抽象类的正确用法啊,就是说,C c=new q();是对的,要是写成C c=new C(),这就错了,这就是要实例化一个抽象类,是错的,但C c=new q();是把一个抽象类指向了一个实例化了它的子类对象,是对的
      

  11.   

    上面几位已经给你说的很明白了;
    第一:C c=new q(); 这个不是abstract类实例化.
    C c=new C();这个才是C类实例化。你试试看行不行?第二:你在class q里加个
    void Display(){
             System.out.println("Welcome javaWorld");
          }
    你看可以不可以调用?
    ****************************************************
    第一个例子,虽然new q()是q的一个实例,但c是一个C类型的变量,因些,你把new q()赋给c的时候,执行了向上转型,c已经被看作是一个C的实例了,这样,C类中没有的接口都被屏蔽了,因此,也就不能调用q类中有的而C类中没有的metoo()方法了。
      

  12.   

    回复:abstract类是不能被实例化的,但是可以声明abstract类的引用,这个引用可以指向其子类的实例对象;
    向上转型是指:对于子类的对象可以用父类引用来指向,虽然实际生成的对象是子类的对象,但是通过父类的引用来指向的,所以通过这个父类的引用只能访问父类中定义的方法;同理,实现接口的类与接口的向上转型与此类似;既然通过这个父类的引用只能访问父类中定义的方法,那么程序2的运行结果是inside,而不是inside abc, 结果是inside的话,那访问的就是子类中的方法而不是父类中的方法
     
      

  13.   

    你可以这样理解:方法也是类里面的一个成员,其实质和成员变量查不多。每个方法可以看作一个指针,指向所要执行的一段代码。
    在你第一个程序里面,父类没有定义metoo方法,对于这个类来说就是没有这个指针,所以第一个编译便会出现错误。
    而第二个程序里面父类定义了metoo方法,于是就有了个叫metoo的指针定向到一段代码,而子类重写了这个方法,相当于将这个指针的指向转到了另一段代码上面。所以当你调用这个方法的时候执行的是子类定义的逻辑。