荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: junire (流星?不看。), 信区: Java
标  题: [合集]就是这篇啊
发信站: 荔园晨风BBS站 (Mon Nov 19 21:46:33 2001), 站内信件

kid (以一种平静的心情来灌水!) 于Tue Nov 13 23:08:14 2001提到:

   哪位高手个解释
class Base {
        int i;
        Base() {
                i = 0;
                add(1);
        }
        void add(int v) {
                i =i + v;
        }
        void print() {
                System.out.println(i);
        }
}

class Extension extends Base {
        Extension() {
                add(2);
        }
        void add(int v) {
        i = i+ v*2;
        }
}

public class Poly {
        public static void main(String args[]) {
                bogo(new Extension());
        }
        static void bogo(Base b) {
                b.add(8);
                b.print();
        }
}

  结果是22,为什么啊?


Lg (创造人生的传奇) 于Wed Nov 14 12:29:03 2001提到:

我不是高手,对这个类的继承理解也不是很透彻,这里只是说说我的想法。
当获取子类Extension的实例时,它会调用相关的构造函数。并且如果这个构造
函数没有显式调用父类的构造函数,那么它会缺省调用super(),所以它先调了
Base(),因为子类Extension已经覆盖了add()的实现,所以Base()里面的add()
实际上也是执行子类的实现。这样i=2, 然后调用了Extension()里面的add(2),
i = 6;最后就是22。



junire (好好学习,天天向上) 于Wed Nov 14 13:12:13 2001提到:

那么我想问一下的是,为什么第二次没有调用base了,而是直接调用了
expesion里的add()方法?



kid (以一种平静的心情来灌水!) 于Wed Nov 14 13:27:25 2001提到:

          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        就这个还是有点不明白。父类的方法怎么会调用子类的方法来实现呢?



tang (-----) 于Wed Nov 14 13:56:04 2001提到:

Java里的方法都是virtual的,也就是所有的调用都是间接的(更准确点叫运行时绑定,
到运行时才决定调用的实际是哪个方法),这类语言的典型实现方法是所有类都有一
张虚表维护每个方法的入口地址,继承时保留基类的虚表并对其进行扩展以登记派生
类新的方法,如果派生类重载基类的方法只是简单地修改从基类继承下来的虚表里相
关的入口项。这样,因为对基类某个方法的调用无论是在基类里还是在派生类里都是
使用同一个虚表的同一个方法的入口地址,所以调的都是同一个方法(派生类的重载
方法,如果有重载的话)。

其实写程序不需要管这些细节,明白java的语言模式就可以了,知道virtual method
的行为如此这般就行了,不用管为什么的,深入点可以知道一下这样做的作用,如virtual
的作用是让同一个名字在不同的上下文(context)里代表不同的意义,增加语言的表现
力,同时可以通过派生的办法(其实是引入新的上下文)更改基类的行为,保持统一的
接口。

呵呵,是理论,现在深大计算机有没有开程序设计理论课,分析比较各种程序设计语
言及其各种可能的实现方法?


Lg (创造人生的传奇) 于Wed Nov 14 15:15:09 2001提到:

你是指那个第二次?
如果是指Extension()构造函数里面的add(),那是因为父类的构造函数已经
调用了。你可以在那个语句前面显式调用super()试试。



Lg (创造人生的传奇) 于Wed Nov 14 15:21:23 2001提到:

这个也是我没有彻底想明白的地方。我觉得这个和类的实例化过程有关。
看看Class.forName().getInstance()源码也许能明白。tang说的应该可以解释这个
问题。


fog (我是一个正直的人) 于Wed Nov 14 15:44:35 2001提到:

这样相当于说:

声明为子类的类对象赋给了基类变量后,用基类变量调用add()的话,那肯定是调用

子类的add()咯!



junire (好好学习,天天向上) 于Wed Nov 14 17:21:52 2001提到:

也就是说整个过程是这样的了:
在调用Extension实例之前先调用它的构造函数
而在构造函数中又默认地调用父类Base地add方法,
然后再调用Extension的add方法,
接下来那个Base b又如何解释啊,它不是调用了父类的方法吗?



kid (以一种平静的心情来灌水!) 于Wed Nov 14 17:29:16 2001提到:

   Base b = new Extension()
  调用的是Extension类的方法add()



fog (我是一个正直的人) 于Wed Nov 14 17:55:01 2001提到:

                                 ~~~~~~~~~~~~~~
                                因为是子类的对像,所以调用的是Extension的add


junire (好好学习,天天向上) 于Wed Nov 14 18:07:56 2001提到:

如果是这样的话,那么就是说方法被重载了,但是如果是这样的话
那么结果就应该是Extension。add(8)
那么结果就是i+=v*2
i=i+v*2=0+16=16



tang (-----) 于Wed Nov 14 18:14:04 2001提到:

过程如此,但最好别这样理解,最好这么想:
实例化一个类:
1、先构造父类,如果有父类的话;
2、初始化本实例的状态,调用本类的构造函数。

以上是个递归定义,父类的构造过程也是一个类的实例化过程,所以父类的构造
函数会被调用。实现语言这一特性的典型方法是编译器在编译时把构造父类的所
有代码(如调某个构造函数等)放在子类的构造代码前,构成完整的类的构造代
码。
从上面的所说的东西,你这个理解应该错了。


Nimarby (海阔天空) 于Wed Nov 14 18:25:41 2001提到:

    new Extension是要初始化的,也就是先初始化基类。再初始化衍生类
    在初始化后i=6;然后6+16=22



fog (我是一个正直的人) 于Wed Nov 14 18:53:23 2001提到:

  i=2;
。再初始化衍生类


loris (不良牛) 于Thu Nov 15 16:16:04 2001提到:

就是说一个对象得初始化调用了两次构造函数?
为什么?



junire (好好学习,天天向上) 于Thu Nov 15 17:36:00 2001提到:

不是我理解的是在调用构造函数时子类默认地调用super。add(),不知道是不是



jjk (想你) 于Thu Nov 15 20:35:57 2001提到:

java里面的都叫方法吧?C++的才叫构造函数

java构造方法在形式和功能上与C++对应的成分相似。在java中,构造方法与它所属的
类同名;它们不返回任何值。构造方法可取零或多个参数为输入,并且可以被重载。

构造方法用于确保所有新的对象以一个有效的初始状态生成。因为java对象总是在堆
(heap)中创建,所以对象的构造方法仅在使用关间词new时才被调用。事实上,除了在用
关键词创建一个对象的时候,在其它使用时候调用构造方法都是非法的.
     例子(合法的调用跟非法调用)

     Square s;//declare s as a reference to a Square
              //no object created and no constructor called
     s = new square(); //Square's default constructor is called
     s.Square();       //Illegal constructor call

    所有的java类都有构造方法。如果你没有声明一个构造方法,编译器会自动为你生成
一个默认的构造方法。与C++不同,每当创建一个新的对象,java保证所有的变量都被
初始化,并给所有未被显示初始化的数据成员赋予默认值。数值类型被初始化为零;
布尔型为false,对象的引用设为null.
    构造方法可调用同一个类中的其他构造方法,或其他超类的构造方法。对其它构造
方法的调用必须是一个构造方法的第一行语句。如果程序没有调用超类的任何一个构造
方法,java会自动调用超类的默认构造方法。


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店