首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 对于Java多态的疑惑 [已结贴,结贴人:sinall]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:12:21 楼主
    class A
    {
    public void fun1()
    {
        func2();
    }
    private void fun2()
    {
        System.out.println("This is A::fun2()");
    }
    }

    class B extends A
    {

    private void fun2()
    {
        System.out.println("This is B::fun2()");
    }
    }

    main()
    {
        B b = new B();
        b.func1();
    }

    请问,为什么会B实例的func1会调用A的func2呢???
    Java的多态到底怎么回事???
    如果我想重写func2,而使得func1调用我重写的func2,该如何做?
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:13:501楼 得分:0
    还有,我希望func2有个默认实现,如果我不重写的话,它就用默认的实现。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:21:092楼 得分:0
    这个不是多态,是 override

    你既然自己实现了 fun2 为何要调用以前的呢?

    super.fun2() 可以调用,不过必须在 B 里面。 而你的 func1 在 A里面
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:26:293楼 得分:0
    兄弟,这个不是基本的Template method模式吗???
    我重写了func2,但是我并没有重写func1啊。。。
    我希望func1调用我重写的func1啊!!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:27:134楼 得分:0
    我希望func1调用我重写的func2,而不是它原来的func2!!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:28:475楼 得分:0
    这个程序在C++里给func2加个virtual肯定没问题。。。
    Java里怎么做?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:33:596楼 得分:10
    问题在于你的fun2()方法是private类型的,在父类的fun1方法中不能调用自类private类型的方法,所以导致只能调用自己的fun2你把fun方法声明的private该城public就可以了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:37:297楼 得分:0
    protected行不?
    func1是接口方法好不好?func2没必要暴露给用户。如果public的话,接口岂不是变大了?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:38:338楼 得分:0
    那你重写fun1不就实现了你想要的!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:39:279楼 得分:0
    呵呵,protected可以,谢天谢地。。。
    Java在面向对象方面还是不如C++方便啊。。。。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:40:5310楼 得分:0
    那你重写fun1不就实现了你想要的!
    ——兄弟,B要继承func1的实现啊。。。重写当然可以,那不是多写了一份代码嘛,你可以看看template method模式!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:54:0711楼 得分:0
        你的fun2()就跟本没有被继承,因为A的fun2()是private,也就是说,B的fun2()是你新定义的一个方法,跟本就不是重写!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 18:55:1912楼 得分:0
    c++只能算半面向对象,你仔细考虑考虑,正因为java是纯面向对象,所以才会有这样的问题发生。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 19:01:4613楼 得分:0
    有点深奥自己实践去了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 19:05:5714楼 得分:0
    引用 2 楼 java2000_net 的回复:
    这个不是多态,是 override

    你既然自己实现了 fun2 为何要调用以前的呢?

    super.fun2() 可以调用,不过必须在 B 里面。 而你的 func1 在 A里面

    这个不是override,由于A类的fun2已经是private了,根本不能被B类继承过来,所以两个类中的fun2不存在override关系,就是两个独立的方法,
    如果是符合override的话那么用B的对象,也就是new B()一定可以调用到B中的fun2方法的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-02 19:49:5815楼 得分:0
    c++只能算半面向对象,你仔细考虑考虑,正因为java是纯面向对象,所以才会有这样的问题发生。
    ——呵呵,纯/半面向对象???面向对象这个概念有确切概念吗?
    ——Java不能多重继承也很让人头疼。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 00:57:4516楼 得分:0
    引用 2 楼 java2000_net 的回复:
    这个不是多态,是 override

    你既然自己实现了 fun2 为何要调用以前的呢?

    super.fun2() 可以调用,不过必须在 B 里面。 而你的 func1 在 A里面

    正确
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:00:3117楼 得分:0
    引用 16 楼 fengalon_software 的回复:
    引用 2 楼 java2000_net 的回复:
    这个不是多态,是 override 

    你既然自己实现了 fun2 为何要调用以前的呢? 

    super.fun2() 可以调用,不过必须在 B 里面。 而你的 func1 在 A里面

    正确


    这个不是override,由于A类的fun2已经是private了,根本不能被B类继承过来,所以两个类中的fun2不存在override关系,就是两个独立的方法,
    如果是符合override的话那么用B的对象,也就是new B()一定可以调用到B中的fun2方法的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:03:1318楼 得分:0
    引用 14 楼 loujianchengdd 的回复:
    引用 2 楼 java2000_net 的回复:
    这个不是多态,是 override 

    你既然自己实现了 fun2 为何要调用以前的呢? 

    super.fun2() 可以调用,不过必须在 B 里面。 而你的 func1 在 A里面

    这个不是override,由于A类的fun2已经是private了,根本不能被B类继承过来,所以两个类中的fun2不存在override关系,就是两个独立的方法,
    如果是符合override的话那么用B的对象,也就是new B()一定可以调用到B中的fun2方法的。

    错了吧!
    override是只要你的访问权限更严格或相同都能覆盖吧!
    比如public f(){} 可以用private,protected,public,以及默认的权限覆盖;
        private f(){} 怎么只能由private覆盖;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:06:3819楼 得分:0
    引用 11 楼 totti_java 的回复:
        你的fun2()就跟本没有被继承,因为A的fun2()是private,也就是说,B的fun2()是你新定义的一个方法,跟本就不是重写!

    同意.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:07:5520楼 得分:10
    恩,不错。不过我认为首先父类的方法对子类是要可见的才可以override,不然不可以的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:13:3621楼 得分:0
    还有在override一个方法时候只能增大它的访问权限不能缩小
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:14:1322楼 得分:0
    18楼好像说反了吧
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:17:1423楼 得分:0
    这是由于B实例已经继承了A类中的方法,所以可以直接用B类来调用A类中的方法,如果你想重写func2的话,那么你必须带有参数,只需在func1的方法中将里面的func2()换成func2(参数)就可以了,这样他调用的就是你写的func2了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:23:5924楼 得分:0
    package com.lou.test;

    import stu.Person;
    public class DBReader extends Person
    {
        private void a()
        {

        }
    }

    package stu;


    public class Person{ 
        static int i;
        public static void main(String[] args)
        {
       
        }
        void a()
        {

        }
    }

    建议看下这2段代码,为什么在类DBReader 中可以把方法a声明为private的呢?如果为override那么应该不能够缩小访问权限的。
    正是因为在Person类中a方法为默认级别对不同包中的类DBReader 是不可见的,所以这个时候编译器把DBReader 中的a方法当作一个新的方法,
    根本不是override,这样才可以把DBReader 中的方法a()生命为private
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:31:1725楼 得分:0
    引用 20 楼 loujianchengdd 的回复:
    恩,不错。不过我认为首先父类的方法对子类是要可见的才可以override,不然不可以的。

    方法不应该是归某个对象拥有的吧!是类里面公有的,当你new一个新对象出来的时候只是把他指向方法的地址(对这个地址的访问应该没问题)放进该对象的一个空间里(这个空间应该不是private).你所说的private应该是针对的变量(不包括覆盖)?
    而且方法的覆盖也是在内存中的一个空间里重新写,并没有真正覆盖原来的那个方法;所以他只是改变了那个地址.
    class A
    {
    public void fun1()
    {
        func2();
    }
    private void fun2()
    {
        System.out.println("This is A::fun2()");
    }
    }

    class B extends A
    {

    private void fun2()
    {
        System.out.println("This is B::fun2()");
    }
    }

    main()
    {
        B b = new B();    //这里应该是改变了超类里面的那个地址?
        b.func1();
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:40:2826楼 得分:0
    引用 24 楼 loujianchengdd 的回复:
    package com.lou.test;

    import stu.Person;
    public class DBReader extends Person
    {
        private void a()
        {

        }
    }

    package stu; 


    public class Person{   
        static int i; 
        public static void main(String[] args) 
        { 
         
        }
        void a()
        {

        }
    }

    建议看下这2段代码,为什么在类DBReader 中可以把方法a声明为private的呢?如果为override…

    你在好好看下。我的意思是说,如果编译器认为这个是方法a为override那么父类中的为默认访问权限,而子类该为private肯定会报错的,
    之所以没有错误就是因为编译器认为这个方法不能构成重载。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:41:3227楼 得分:0
    引用 22 楼 loujianchengdd 的回复:
    18楼好像说反了吧

    对不起是说反了,但是在书上才找到一个列子
    class Parent{
      int a;
      private int g(int a,int b){
      ...
      }
    }
    class Child extends Parent{
      int a;
      int b;
      public int g(int a,int b){          //增大访问权限的覆盖,(按你说的,这个也是新定义的?)
      ...
    }
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:46:1128楼 得分:0
    引用 24 楼 loujianchengdd 的回复:
    package com.lou.test;

    import stu.Person;
    public class DBReader extends Person
    {
        private void a()
        {

        }
    }

    package stu; 


    public class Person{   
        static int i; 
        public static void main(String[] args) 
        { 
         
        }
        void a()
        {

        }
    }

    建议看下这2段代码,为什么在类DBReader 中可以把方法a声明为private的呢?如果为override…

    我承认自己的错误,我是为学习来的,感谢你的指点.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 01:52:5829楼 得分:0
    呵呵,也不知道你是真明白了,还是.....反正我这个人在技术方面就爱较真,呵呵,没别的意思,只是希望大家都能有学到更多的东西
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 02:05:0930楼 得分:0
    引用 29 楼 loujianchengdd 的回复:
    呵呵,也不知道你是真明白了,还是.....反正我这个人在技术方面就爱较真,呵呵,没别的意思,只是希望大家都能有学到更多的东西

    嘿嘿,我承认我刚才说的那个权限范围错了,但没说lz的那个题我搞错了,
    访问控制符可以使用与超类相同或比超类权限更大的控制符
    class Parent{
      int a;
      private int g(int a,int b){
      ...
      }
    }
    class Child extends Parent{
      int a;
      int b;
      public int g(int a,int b){          //增大访问权限的覆盖,(按你说的,这个也是新定义的?如果改成private也应该是相同道理,只是权限没变化)
      ...
    }
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 02:12:2031楼 得分:0
    package com.lou.test; 

    import stu.Person; 
    public class DBReader extends Person 

        private void a() 
        { 

        } 


    package stu; 


    public class Person{   
        static int i; 
        public static void main(String[] args) 
        { 
         
        } 
        void a() 
        { 

        } 

    呵呵。你的那个例子同属于一个包里面看不出来什么的。还是让你看看我的这个代码,由于父类与子子类处于不同的包中,所以父类Person 中的a()方法
    对于子类DBReader不可见,这个时候子类的a()方法你说还是override吗?如果是就不能声明为private,缩小了权限,同理,也就是说,对于子类不可见的
    父类中的方法,子类中就不能override,只不过,如果父类为private了,子类没办法再缩小权限,如果可以缩小权限也一定不会报错误,因为不是override
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 02:21:3732楼 得分:0
    我知道权限范围不能缩小了,谢谢,但你也要看清楚我在上面写出的那个列子,不是缩小范围了,现在也不是说的那个问题而是讲的lz那个,我认为子类里面的private不用改也应该是覆盖。而且反驳那些说是新定义的朋友。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 02:33:0633楼 得分:0
    "loujianchengdd "想下还真觉得你说的有道理,但我查了几本书,都说这个属于覆盖,脑袋疼....
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-03 02:38:5134楼 得分:0
    呵呵,暂时不讨论这个问题,其实有的时候书上也不一定对,必定现在能写书的人太多了阿。