Javascript中的Trait与代码重用

开发 前端
我们知道,OOP中最普遍的代码重用方式是通过继承,但是,继承有一些缺点,其中最为主要的是继承是一种isa关系,父子类之间的关系太过紧密,而对于像JAVA这门语言而言,只能支持单继承,使得很多时候不能不进行代码拷贝这样的事情。

我们知道,OOP中最普遍的代码重用方式是通过继承,但是,继承有一些缺点,其中最为主要的是继承是一种isa关系,父子类之间的关系太过紧密,而对于像JAVA这门语言而言,只能支持单继承,使得很多时候不能不进行代码拷贝这样的事情。

举个例子,假设我们要建模动物。最底层是一个Animal对象,下面有猫科,犬科。然后猫科下有猫,老虎。犬科下有狗和狼。 猫能够miao,狗能够叫,老虎和狼都能够狩猎,这个时候问题来了,由于狩猎这个特性是老虎和狼都有的,但是老虎以及从猫科继承,狼已经从犬科继承,它们都已经无法通过继承来获得狩猎这个能力了。

让我们来看看Trait如何来解决这个问题。 Trait从表面上看和一个类很类似,有属性和方法,但是它必须依附于一个类才能起作用。同时多个Traits可以组合成一个Trait。如果不同的 Traits中属性或者方法有冲突的话,可以选择重命名属性的方法来决议冲突。如果冲突没有决议的话,组合Traits会抛出异常。

这样,类层次仍然像前面描述的一样,我们把狩猎定义为一个Trait,然后在构建老虎和狼的类的时候把Trait融入进去。这样老虎和狼就获得了狩猎的能力了。

由于Java语言的限制,没有一种华丽的方法来实现Trait。让我们来看看基于原型的Javascript语言如何实现Trait。这个其实从一 个侧面证明基于原型的Javascript和基于类的Java相比,对于OOP而言更加灵活和强大。为了缩减代码的大小,这里我使用light- traits这个JS库。因为完整实现一个Traits库超出这篇文章的范围。

  1. var util = require('util'); 
  2. var Trait = require('light-traits').Trait; 
  3. var expect = require('chai').expect; 
  4. var _ = require('lodash'); 
  5. function inherits(constructor, parentConstructor, trait, properties) { 
  6.   util.inherits(constructor, parentConstructor); 
  7.   if (properties !== undefined) 
  8.     _.extend(constructor.prototype, properties); 
  9.   if (trait !== undefined) 
  10.     constructor.prototype = trait.create(constructor.prototype); 
  11.  
  12. function Animal() {} 
  13. Animal.prototype = { 
  14.   isAlive: true, 
  15.   eat: function (food) { 
  16.     console.log("omnomnom, I'm eating: " + food); 
  17.   }, 
  18.   sleep: function () { 
  19.     console.log('zzzz'); 
  20.   }, 
  21.   die: function () { 
  22.     this.isAlive = false
  23.     console.log("I'm dead"); 
  24.   } 
  25. }; 
  26.  
  27. function CatFamily() {} 
  28. inherits(CatFamily, Animal); 
  29. function DogFamily() {} 
  30. inherits(DogFamily, Animal); 
  31.  
  32. var TMeow = Trait({ 
  33.   meow: function () { 
  34.     console.log('meow meow'); 
  35.   } 
  36. }); 
  37. function Cat() {} 
  38. inherits(Cat, CatFamily, TMeow); 
  39.  
  40. var cat = new Cat(); 
  41. cat.meow(); 
  42.  
  43. var TBark = Trait({ 
  44.   bark: function () { 
  45.     console.log('woof woof'); 
  46.   } 
  47. }); 
  48. function Dog() {} 
  49. inherits(Dog, DogFamily, TBark); 
  50.  
  51. var dog = new Dog(); 
  52. dog.bark(); 
  53.  
  54.  
  55. var THunt = Trait({ 
  56.   huntCount: 0, 
  57.   hunt: function () { 
  58.     console.log('looking for food', this.huntCount++, 'times'); 
  59.  
  60.   }, 
  61.   kill: function (animal) { 
  62.     animal.die(); 
  63.     console.log('I killed animal'); 
  64.   } 
  65. }); 
  66.  
  67. function Tiger() {} 
  68. inherits(Tiger, CatFamily, THunt, { 
  69.   roar: function () { 
  70.     console.log("roar...roar..."); 
  71.   } 
  72. }); 
  73.  
  74. var tiger = new Tiger(); 
  75. expect(tiger).to.be.instanceOf(CatFamily); 
  76. expect(tiger).to.have.property('hunt'); 
  77. expect(tiger).to.have.property('kill'); 
  78. expect(tiger).to.not.have.property('meow'); 
  79. expect(tiger.isAlive).to.be.equal(true); 
  80. tiger.hunt(); 
  81. tiger.eat('meat'); 
  82. tiger.roar(); 
  83.  
  84. function Wolf() {} 
  85. inherits(Wolf, DogFamily, Trait.compose(TBark, THunt)); 
  86.  
  87. var wolf = new Wolf(); 
  88. expect(wolf).to.be.instanceOf(DogFamily); 
  89. expect(wolf).to.have.property('hunt'); 
  90. expect(wolf).to.have.property('kill'); 
  91. expect(wolf).to.have.property('bark'); 
  92. expect(wolf.isAlive).to.be.equal(true); 
  93. wolf.bark(); 
  94. wolf.hunt(); 
  95. wolf.hunt(); 
  96. wolf.sleep(); 
  97. wolf.kill(cat); 
  98. expect(cat.isAlive).to.be.equal(false); 
  99. expect(wolf.huntCount).to.be.equal(2); 

原文链接:http://www.ituring.com.cn/article/64103

责任编辑:陈四芳 来源: 图灵社区
相关推荐

2018-11-08 15:50:18

前端Javascript重用性

2009-09-09 14:09:35

Scala Trait

2023-05-29 13:56:00

JSReact

2024-06-13 10:11:33

WPFCommand命令模式

2017-01-10 13:37:15

PHPTrait应用

2024-01-03 08:00:00

Java软件开发代码

2011-07-21 13:24:14

java

2020-06-12 08:21:58

JavaScript代码开发

2024-06-28 01:13:59

工具C#代码

2009-08-19 04:16:00

泛型代码重用

2009-03-11 15:30:05

evalwithJavascript

2020-06-02 09:06:31

VueTransition前端

2023-11-29 13:59:00

trait定义接口

2017-02-28 15:48:11

Scala Trait设计模式框架

2017-07-24 09:45:15

JavaScript语法代码

2023-11-23 13:07:18

代码Golang

2009-03-13 15:24:50

catchDisposeWCF

2010-01-25 11:37:30

2017-07-26 17:38:10

JavaScriptBabel

2023-08-29 09:00:00

JavaScript工具
点赞
收藏

51CTO技术栈公众号