JavaScript 和 Java 都是面向对象的编程语言,但它们在实现继承的方式上有很大的不同。下面我将详细介绍这两种语言在继承方面的区别和联系。
继承的基本概念
继承是一种机制,它允许一个类(子类)继承另一个类(父类)的属性和方法。这有助于代码重用,并且可以建立类之间的层次结构。
JavaScript 的继承
原型链
- 原型:每个 JavaScript 对象都有一个内部属性
[[Prototype]]
,指向另一个对象,这个对象就是原型。 - 构造函数:JavaScript 中的构造函数用于创建对象实例。每个构造函数都有一个默认的
prototype
属性,这个属性是一个对象,它会被用作所有通过该构造函数创建的对象的原型。 - 继承方式:JavaScript 使用原型链来实现继承。当试图访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript 会查找它的原型对象,直到找到这个属性或者到达原型链的末端(通常是
null
)。
1function Animal(name) {
2 this.name = name;
3}
4
5Animal.prototype.speak = function() {
6 console.log(this.name + ' makes a noise.');
7};
8
9function Dog(name) {
10 Animal.call(this, name); // 调用父类构造函数
11}
12
13Dog.prototype = Object.create(Animal.prototype); // 设置原型
14Dog.prototype.constructor = Dog; // 修正构造函数指针
15
16Dog.prototype.speak = function() {
17 console.log(this.name + ' barks.');
18};
19
20let dog = new Dog('Rex');
21dog.speak(); // 输出: Rex barks.
ES6 类语法
- class 关键字:ES6 引入了
class
关键字,使得继承更加直观。 - extends 关键字:使用
extends
来声明一个类是从另一个类派生而来的。 - super 关键字:用来调用父类的方法或构造函数。
1class Animal {
2 constructor(name) {
3 this.name = name;
4 }
5
6 speak() {
7 console.log(this.name + ' makes a noise.');
8 }
9}
10
11class Dog extends Animal {
12 constructor(name) {
13 super(name); // 调用父类构造函数
14 }
15
16 speak() {
17 console.log(this.name + ' barks.');
18 }
19}
20
21let dog = new Dog('Rex');
22dog.speak(); // 输出: Rex barks.
Java 的继承
单继承
- 单继承:Java 只支持单一继承,即一个类只能直接继承自一个父类。
- 关键字
extends
:使用extends
关键字来声明一个类继承自另一个类。 - 构造器:子类可以通过
super()
调用父类的构造器。 - 方法覆盖:子类可以覆盖(override)父类的方法以提供新的实现。
1public class Animal {
2 private String name;
3
4 public Animal(String name) {
5 this.name = name;
6 }
7
8 public void speak() {
9 System.out.println(name + " makes a noise.");
10 }
11}
12
13public class Dog extends Animal {
14 public Dog(String name) {
15 super(name); // 调用父类构造函数
16 }
17
18 @Override
19 public void speak() {
20 System.out.println(name + " barks.");
21 }
22}
23
24public class Main {
25 public static void main(String[] args) {
26 Dog dog = new Dog("Rex");
27 dog.speak(); // 输出: Rex barks.
28 }
29}
区别
-
多继承 vs 单继承:
- JavaScript 支持多重继承(通过组合多个原型链),而 Java 只支持单一继承。
-
动态 vs 静态:
- JavaScript 是动态类型的,可以在运行时改变对象的结构。Java 是静态类型的,在编译时就确定了类型。
-
接口与抽象类:
- Java 提供了接口和抽象类的概念,这些在 JavaScript 中并没有直接对应的特性。虽然 ES6 引入了
interface
,但它更像是 TypeScript 的特性。
- Java 提供了接口和抽象类的概念,这些在 JavaScript 中并没有直接对应的特性。虽然 ES6 引入了
-
构造函数调用:
- 在 JavaScript 中,必须显式地调用父类的构造函数(使用
call
或super
)。而在 Java 中,如果没有显式调用父类的构造函数,会自动调用无参构造函数。
- 在 JavaScript 中,必须显式地调用父类的构造函数(使用
-
方法覆盖:
- Java 中使用
@Override
注解来明确表示方法覆盖,这在 JavaScript 中是隐式的。
- Java 中使用
联系
-
基于类的继承:
- 两种语言都支持基于类的继承模式。
-
构造函数:
- 两种语言都有构造函数的概念,用于初始化对象。
-
方法覆盖:
- 两种语言都允许子类覆盖父类的方法以提供新的实现。
-
封装:
- 两种语言都支持封装,尽管实现方式不同,但都可以隐藏对象的内部状态并暴露公共接口。
原型继承示例
原型继承特色
基于函数的原型继承
一点理解:
1.函数的prototype相当于是,你可以自己在这个属性上加一些模板属性和方法。然后这个子对象就会根据你在prototype里设置的模板来创建
2.原型继承,就是直接以对象实例为依据去继承。继承的方式就是先定义好父对象,然后用Object.creat()方法,传递父对象进去,然后创建子对象。而子对象特有的方法和属性,是在后续在加上的。
3.java的继承发生在类上,js的继承发生在对象上。