Câu trả lời:
Trong Java , tất cả các phương thức không tĩnh theo mặc định là " các hàm ảo " . Chỉ các phương thức được đánh dấu bằng từ khóa cuối cùng , không thể bị ghi đè, cùng với các phương thức riêng , không được kế thừa, là không ảo .
Đúng. Trong thực tế, tất cả các phương thức cá thể trong Java là ảo theo mặc định. Chỉ một số phương thức nhất định không ảo:
Dưới đây là một số ví dụ:
Các chức năng ảo "bình thường"
Ví dụ sau đây là từ một phiên bản cũ của trang wikipedia được đề cập trong câu trả lời khác.
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 {}
Đầu ra:
Tôi ăn như một con thú chung chung. Tôi ăn như một con cá! Tôi ăn như một con cá vàng! Tôi ăn như một con thú chung chung.
Ví dụ với các hàm ảo có giao diện
Các phương thức giao diện Java đều là ảo. Chúng phải là ảo vì chúng dựa vào các lớp triển khai để cung cấp các cài đặt phương thức. Mã để thực thi sẽ chỉ được chọn trong thời gian chạy.
Ví dụ:
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
}
}
Ví dụ với các hàm ảo với các lớp trừu tượng.
Tương tự như giao diện Các lớp trừu tượng phải chứa các phương thức ảo vì chúng dựa vào việc thực hiện các lớp mở rộng. Ví dụ:
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.
}
}
Tất cả các hàm trong Java là ảo theo mặc định.
Bạn phải tìm cách viết các hàm không ảo bằng cách thêm từ khóa "cuối cùng".
Điều này trái ngược với mặc định của C ++ / C #. Các hàm lớp không ảo theo mặc định; bạn làm cho chúng như vậy bằng cách thêm công cụ sửa đổi "ảo".
Tất cả các phương thức cá thể không riêng tư là ảo theo mặc định trong Java.
Trong C ++, các phương thức riêng tư có thể là ảo. Điều này có thể được khai thác cho thành ngữ không giao diện ảo (NVI). Trong Java, bạn cần làm cho các phương thức có thể ghi đè NVI được bảo vệ.
Từ Đặc tả ngôn ngữ Java, v3:
8.4.8.1 Ghi đè (bằng phương thức sơ thẩm) Phương thức cá thể m1 được khai báo trong lớp C ghi đè phương thức cá thể khác, m2, được khai báo trong lớp A iff tất cả những điều sau đây là đúng:
- C là một lớp con của A.
- Chữ ký của m1 là một phần phụ (§8.4.2) của chữ ký m2.
- * M2 là công khai, được bảo vệ hoặc khai báo với quyền truy cập mặc định trong cùng gói với C hoặc * m1 ghi đè phương thức m3, m3 khác với m1, m3 khác với m2, sao cho m3 ghi đè lên m2.
Trong Java, tất cả các biến & hàm công khai (không riêng tư) là Ảo theo mặc định. Hơn nữa các biến & chức năng sử dụng từ khóa cuối cùng không phải là ảo .