浅谈Java中的"虚函数"

简述

虚函数是面向对象程序设计的一个重要的方法,但是在一些书籍当中,并没有很好的介绍虚函数的作用,导致一些初学者并不能很好的理解虚函数,所以本文尽量以通熟易懂的语言介绍Java虚函数。

什么是虚函数

在C++中,虚函数通过virtual关键字定义,实现在类的继承当中,编译器通过判断对象的类型,在调用函数时,执行对应的函数。使用维基百科上的例子,来解释一下虚函数的作用:

# include <iostream>
# include <vector>

using namespace std;
class Animal
{
public:
    virtual void eat() const { cout << "I eat like a generic Animal." << endl; }
    virtual ~Animal() {}
};
 
class Wolf : public Animal
{
public:
    void eat() const { cout << "I eat like a wolf!" << endl; }
};
 
class Fish : public Animal
{
public:
    void eat() const { cout << "I eat like a fish!" << endl; }
};
 
int main()
{
    std::vector<Animal*> animals;
    animals.push_back( new Animal() );
    animals.push_back( new Wolf() );
    animals.push_back( new Fish() );
    for( std::vector<Animal*>::const_iterator it = animals.begin();it != animals.end(); ++it) 
    {
        (*it)->eat();
        delete *it;
    }
 
   return 0;
}

在代码中,WolfFish类继承了Animal类,定义了eat()为一个虚函数。vector存储的是Animal类的类型集合,但在向vector添加元素时,把Wolf类型以及Fish类型添加进去。所以,在后边调用eat()的时候,编译器会调用对应类下的eat()函数。输出

I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!

即实现了多态这一概念。

Java中的”虚函数”

在Java中,虽然没有像C++那样的刻意定义了虚函数,但Java默认每一个函数都是虚函数,它通过动态绑定实现了虚函数的功能,如下面的例子

public class Animal {
   public void eat() { System.out.println("I eat like a generic Animal."); 
}
 
public class Wolf extends Animal {
   public void eat() { System.out.println("I eat like a wolf!"); }
}
 
public class Fish extends Animal {
   public void eat() { System.out.println("I eat like a fish!"); }
}
 
   public static void main(String[] args) {
      List<Animal> animals = new LinkedList<Animal>();

      animals.add(new Animal());
      animals.add(new Wolf());
      animals.add(new Fish());
      for (Animal currentAnimal : animals) {
         currentAnimal.eat();
      }
   }
}

上面的代码中,与C++一样,WolfFish类继承了Animal类,也定义了eat()为一个虚函数。但是却没有进行额外声明,Java虚拟机会在程序运行时,判断对象的类型,分别调用适当的方法。所以程序输出也和C++相同。如果程序员希望函数不具有虚函数的功能,可以在定义函数时,加上final即可。

小结

虚函数存在的意义就是为了实现多态。使程序在运行阶段动态地选择合适的成员函数,从而实现以共同的方法,但因对象差异而采用不同的策略。 而Java通过动态绑定,不仅实现了虚函数的功能,也使得代码逻辑更为简洁。

本文链接:参与评论 »

--EOF--

提醒:本文最后更新于 910 天前,文中所描述的信息可能已发生改变,请谨慎使用。

Comments