实现方式和继承方式有什么区别呢?

本文详细比较了Java中通过继承Thread类与实现Runnable接口创建线程的优劣,包括代码共享、多线程资源管理及Java单继承限制等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

两种方式区别:

继承Thread: 线程代码存放Thread子类run方法中。

实现Runnable,线程代码存在接口的子类的run方法

实现Runnable接口相对于继承Thread类来说,有如下的显著优势:
   1.适合多个相同代码的线程去处理同一个资源的情况,如下例子,继承是创建三个线程对象,每个都有十张票,但是实现的方式是创建一个线程对象,这样实现的方式就能共享十张票了.
   2.可以避免由于java的单继承特性带来的局限
   3.增强了程序的健壮性,代码能够被多个线程共享,代码与数据时独立的

给你个例子,你自己取运行就知道了,好好对比下

 class MyThread extends Thread{        // 继承Thread类,作为线程的实现类
         private int ticket = 10 ;                // 表示一共有10张票
         public void run(){        // 覆写run()方法,作为线程 的操作主体
                 for(int i=0;i<100;i++){
                         if(this.ticket>0){
                                 System.out.println("卖票:ticket = " + ticket--) ;
                         }
                 }
         }
 };
 public class ThreadDemo0{
         public static void main(String args[]){
                 MyThread mt1 = new MyThread() ;         // 创建线程对象,此时线程有十张票
                 MyThread mt2 = new MyThread() ;         // 创建线程对象,此时线程有十张票
                 MyThread mt3 = new MyThread() ;         // 创建线程对象,此时线程有十张票
                 mt1.run() ;        // 调用线程主体执行线程
                 mt2.run() ;        // 调用线程主体执行线程
                 mt3.run() ;        // 调用线程主体执行线程
         }
 };
 
 
 class MyThread implements Runnable{        // 继承Thread类,作为线程的实现类
         private int ticket = 10 ;                // 表示一共有10张票
         public void run(){        // 覆写run()方法,作为线程 的操作主体
                 for(int i=0;i<100;i++){
                         if(this.ticket>0){
                                 System.out.println("卖票:ticket = " + ticket--) ;
                         }
                 }
         }
 };
 public class RunnableDemo0{
         public static void main(String args[]){
                 MyThread mt = new MyThread() ;         // 创建线程对象,此时线程有十张票
                 new Thread(mt).run() ;        // 调用线程主体执行线程
                 new Thread(mt).run() ;        // 调用线程主体执行线程
                 new Thread(mt).run() ;        // 调用线程主体执行线程
         }
 };

简单的来说,就是继承和实现接口的区别。
1、当使用继承的时候,主要是为了不必重新开发,并且在不必了解实现细节的情况下拥有了父类我所需要的特征。它也有一个很大的缺点,那就是如果我们的类已经从一个类继承(如小程序必须继承自 Applet 类),则无法再继承 Thread 类,
2、java只能单继承,因此如果是采用继承Thread的方法,那么在以后进行代码重构的时候可能会遇到问题,因为你无法继承别的类了,在其他的方面,两者之间并没什么太大的区别。
3、implement Runnable是面向接口,扩展性等方面比extends Thread好。
4、使用 Runnable 接口来实现多线程使得我们能够在一个类中包容所有的代码,有利于封装,它的缺点在于,我们只能使用一套代码,若想创建多个线程并使各个线程执行不同的代码,则仍必须额外创建类,如果这样的话,在大多数情况下也许还不如直接用多个类分别继承 Thread 来得紧凑。

<think>好的,用户问的是如何在JavaScript中实现继承,以及有哪些方式。我需要先回忆一下JS继承的各种方法,然后组织成一个清晰的回答。 首先,JS的继承主要是基于原型的,这传统的类继承语言不同。用户可能已经了解过原型链,但需要系统地总结各种方式。常见的继承方式包括原型链继承、构造函数继承、组合继承,还有寄生组合继承、ES6的class继承等等。 接下来,我需要逐一解释每种方法的实现原理,以及它们的优缺点。比如原型链继承的问题在于引用类型的共享,构造函数继承不能继承原型方法,组合继承结合了两者,但会有重复属性的问题。寄生组合继承通常被认为是最佳方式,而ES6的class语法则是语法糖,底层还是基于原型。 用户可能对每种方法的具体代码示例感兴趣,所以需要给出简短的例子,比如原型链继承的例子,说明子类原型指向父类实例。构造函数继承则是通过call或apply调用父类构造函数。组合继承则结合两者,既调用构造函数又设置原型。 还要注意提到ES6的class extendssuper关键字,这是现在更推荐的方式,但需要解释它背后的原理还是基于原型链。 在总结的时候,应该对比各种方法的优缺点,帮助用户根据不同场景选择合适的方式。比如如果需要使用ES6语法,推荐class;如果考虑兼容性,可能用寄生组合继承。 另外,用户可能是在准备面试,所以需要强调这些继承方式是常见的面试题,尤其是组合继承寄生组合继承区别,以及ES6的实现。要确保回答结构清晰,逐步引导,帮助用户理解不同方法的演进过。 最后,检查是否有遗漏的方式,比如原型式继承寄生式继承,虽然这些可能用得少,但作为知识完整性还是应该提到。同时,确保术语准确,比如原型链、构造函数、实例等概念正确使用,避免混淆。</think>--- ### JavaScript继承实现方式详解 JavaScript的继承主要基于 **原型链** 机制,以下是常见的6种继承方式及其核心原理: --- #### 一、**原型链继承** **实现方式**:将子类的原型对象指向父类的实例 ```javascript function Parent() { this.name = 'Parent'; } Parent.prototype.say = function() { console.log(this.name); }; function Child() {} Child.prototype = new Parent(); // 关键:子类原型指向父类实例 const child = new Child(); child.say(); // 输出 "Parent" ``` **缺点**: 1. 所有子类实例共享父类**引用类型属性**(如数组) 2. 无法向父类构造函数传参 --- #### 二、**构造函数继承** **实现方式**:在子类构造函数中调用父类构造函数 ```javascript function Parent(name) { this.name = name; this.colors = ['red', 'blue']; } function Child(name) { Parent.call(this, name); // 关键:复制父类属性到子类实例 } const child1 = new Child('Tom'); child1.colors.push('green'); // 仅修改child1的colors const child2 = new Child('Jerry'); console.log(child2.colors); // 输出 ['red', 'blue'] ``` **优点**: - 解决引用类型共享问题 - 支持向父类传参 **缺点**: - 无法继承父类原型上的方法 --- #### 三、**组合继承**(经典继承) **实现方式**:构造函数继承 + 原型链继承 ```javascript function Parent(name) { this.name = name; } Parent.prototype.say = function() { console.log(this.name); }; function Child(name) { Parent.call(this, name); // 第1次调用Parent } Child.prototype = new Parent(); // 第2次调用Parent Child.prototype.constructor = Child; const child = new Child('Tom'); child.say(); // 输出 "Tom" ``` **缺点**: - 父类构造函数被调用两次(性能问题) - 子类实例原型上存在重复属性 --- #### 四、**寄生组合继承**(最优解) **实现方式**:通过`Object.create()`优化原型链 ```javascript function inheritPrototype(Child, Parent) { const prototype = Object.create(Parent.prototype); // 创建父类原型的副本 prototype.constructor = Child; Child.prototype = prototype; } function Parent(name) { this.name = name; } Parent.prototype.say = function() { console.log(this.name); }; function Child(name) { Parent.call(this, name); } inheritPrototype(Child, Parent); // 关键步骤 const child = new Child('Tom'); child.say(); // 输出 "Tom" ``` **优点**: - 只调用一次父类构造函数 - 避免原型链上的冗余属性 --- #### 五、**ES6 Class继承** **实现方式**:使用`extends``super`关键字 ```javascript class Parent { constructor(name) { this.name = name; } say() { console.log(this.name); } } class Child extends Parent { constructor(name) { super(name); // 必须调用super } } const child = new Child('Tom'); child.say(); // 输出 "Tom" ``` **本质**:ES6的语法糖,底层仍基于寄生组合继承 --- #### 六、其他方式 1. **原型式继承**(类似`Object.create`) 2. **寄生式继承**(工厂函数增强对象) --- ### 总结与对比 | 继承方式 | 优点 | 缺点 | 适用场景 | |----------------|-------------------------------|-------------------------------|-----------------------| | 原型链继承 | 简单 | 引用类型共享/无法传参 | 简单原型扩展 | | 构造函数继承 | 隔离实例属性 | 无法继承原型方法 | 需要独立属性时 | | 组合继承 | 解决前两者缺点 | 父类构造函数重复执行 | 传统项目 | | 寄生组合继承 | 最优性能/无冗余属性 | 实现较复杂 | 现代项目推荐方案 | | ES6 Class继承 | 语法简洁/易维护 | 需支持ES6环境 | 现代开发首选 | --- ### 关键理解点 1. **原型链本质**: - 当访问对象属性时,JavaScript会沿`__proto__`链向上查找 - `Child.prototype.__proto__ = Parent.prototype` 2. **super的作用**: - 在ES6中,`super`相当于`Parent.call(this)` + 继承原型方法 3. **开发建议**: - 现代项目优先使用 **ES6 Class继承** - 需要兼容旧环境时选择 **寄生组合继承**
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值