【问题标题】:Can you write virtual functions / methods in Java?你能用Java写虚函数/方法吗?
【发布时间】:2011-05-31 15:40:18
【问题描述】:

是否可以像在 C++ 中那样在 Java 中编写 virtual 方法?

或者,是否有一种适当的 Java 方法可以实现并产生类似的行为?我可以举一些例子吗?

【问题讨论】:

    标签: java virtual virtual-functions


    【解决方案1】:

    默认情况下,Java 中的所有函数都是虚函数。

    您必须通过添加“final”关键字来编写非虚拟函数。

    这与 C++/C# 默认设置相反。默认情况下,类函数是非虚拟的;您可以通过添加“虚拟”修饰符来制作它们。

    【讨论】:

    • 克劳斯回答中所述的私有函数也是非虚拟的。
    【解决方案2】:

    来自wikipedia

    Java 中,所有非静态方法都由 仅默认“虚拟函数。” 标有关键字final的方法, 不能被覆盖,以及 私有方法,不是 继承,是非虚拟的

    【讨论】:

    • HereJon Skeet 的答案之一。
    • 我想知道这是否真的是真的,因为对于我所读到的内容,在 Java 中,动态方法分派仅发生在调用该方法的对象上 - 正如 here 所解释的那样,示例解释了虚拟C++ here 的函数对 java 无效。
    • @QuaziIrfan 这就是 Java 和 C# 之间的区别。
    【解决方案3】:

    所有非私有实例方法在Java中默认是虚拟的。

    在 C++ 中,私有方法可以是虚拟的。这可以用于非虚拟接口 (NVI) 习惯用法。在 Java 中,您需要保护 NVI 的可覆盖方法。

    来自 Java 语言规范 v3:

    8.4.8.1 覆盖(通过实例方法)实例方法 m1 在 C 类中声明的覆盖 声明了另一个实例方法 m2 如果满足以下所有条件,则属于 A 类 是真的:

    1. C 是 A 的子类。
    2. m1 的签名是签名的子签名(第 8.4.2 节) 平方米。
    3. 要么 * m2 是公共的、受保护的或声明为在 与 C 相同的包,或 * m1 覆盖一个方法 m3,m3 不同于 m1,m3 不同于 m2,这样 m3 会覆盖 m2。

    【讨论】:

      【解决方案4】:

      是的,您可以在 Java 中编写虚拟“函数”。

      【讨论】:

        【解决方案5】:

        你会用Java写虚函数吗?

        是的。事实上,Java 中的所有实例方法在默认情况下都是虚拟的。只有某些方法不是虚拟的:

        • 类方法(因为通常每个实例都包含有关其特定方法的 vtable 指针等信息,但此处没有可用的实例)。
        • 私有实例方法(因为没有其他类可以访问该方法,调用实例始终具有定义类本身的类型,因此在编译时明确知道)。

        这里有一些例子:

        “普通”虚函数

        以下示例来自另一个答案中提到的维基百科页面的old version

        import java.util.*;
        
        public class Animal 
        {
           public void eat() 
           { 
              System.out.println("I eat like a generic Animal."); 
           }
        
           public static void main(String[] args) 
           {
              List<Animal> animals = new LinkedList<Animal>();
        
              animals.add(new Animal());
              animals.add(new Fish());
              animals.add(new Goldfish());
              animals.add(new OtherAnimal());
        
              for (Animal currentAnimal : animals) 
              {
                 currentAnimal.eat();
              }
           }
        }
        
        class Fish extends Animal 
        {
           @Override
           public void eat() 
           { 
              System.out.println("I eat like a fish!"); 
           }
        }
        
        class Goldfish extends Fish 
        {
           @Override
           public void eat() 
           { 
              System.out.println("I eat like a goldfish!"); 
           }
        }
        
        class OtherAnimal extends Animal {}
        

        输出:

        我像普通动物一样吃东西。 我吃得像鱼! 我吃得像金鱼! 我像普通动物一样吃东西。

        带有接口的虚函数示例

        Java interface methods 都是虚拟的。它们必须是虚拟的,因为它们依赖于实现类来提供方法实现。要执行的代码只会在运行时被选中。

        例如:

        interface Bicycle {         //the function applyBrakes() is virtual because
            void applyBrakes();     //functions in interfaces are designed to be 
        }                           //overridden.
        
        class ACMEBicycle implements Bicycle {
            public void applyBrakes(){               //Here we implement applyBrakes()
               System.out.println("Brakes applied"); //function
            }
        }
        

        带有抽象类的虚函数示例。

        类似于接口Abstract classes必须包含虚方法,因为它们依赖于扩展类的实现。例如:

        abstract class Dog {                   
            final void bark() {               //bark() is not virtual because it is 
                System.out.println("woof");   //final and if you tried to override it
            }                                 //you would get a compile time error.
        
            abstract void jump();             //jump() is a "pure" virtual function 
        }                                     
        class MyDog extends Dog{
            void jump(){
                System.out.println("boing");    //here jump() is being overridden
            }                                  
        }
        public class Runner {
            public static void main(String[] args) {
                Dog dog = new MyDog();       // Create a MyDog and assign to plain Dog variable
                dog.jump();                  // calling the virtual function.
                                             // MyDog.jump() will be executed 
                                             // although the variable is just a plain Dog.
            }
        }
        

        【讨论】:

        • 这一定是最完整的答案。由于 java 没有关键字,它提供了两种实现虚函数的方法。谢谢。
        • 比维基百科引文更好的答案。来自 c++ 并且对我的 Java 研究很懒惰,所以我一直在寻找抽象。
        • @David 这个答案如何更好?维基百科的引用是完整的、简洁的和正确的。相比之下,这个答案没有提到房间里的大象:默认情况下,Java 中的 所有 函数(维基百科文章中列出的例外情况)是虚拟的。虚函数既不需要抽象类也不需要接口,所以这只会增加误导性的噪音。然后这“需要出色的沟通技巧和对基本原则的深入掌握”......天哪。那是一个自证其词:没有人会用它浪费宝贵的磁盘空间。
        • 维基百科的帖子不如这个答案,也不太具体,因为它是关于任何语言的虚函数概念,而不仅仅是 java。维基百科页面中给出的示例是用 C 编写的,充其量只是一个不完整的示例,而且更具误导性。有关所有虚拟函数的详细信息,并且您不需要抽象类或接口来使虚拟函数成为噪音。我从来没有说过它们是必需的,你误读了。我不明白你的最后一点,你是否因为你不喜欢这个问题而要我删除它?
        • 晚了几年,但答案很棒
        【解决方案6】:

        在 Java 中,所有公共(非私有)变量和函数默认都是虚拟。 此外,使用关键字 final 的变量和函数不是 virtual

        【讨论】:

        • “虚拟变量”是什么意思?
        猜你喜欢
        • 1970-01-01
        • 2011-01-28
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 1970-01-01
        • 1970-01-01
        • 2010-11-16
        • 1970-01-01
        相关资源
        最近更新 更多