• Javascript中的Trait与代码重用


    Javascript中的Trait与代码重用

    来源 http://www.ituring.com.cn/article/64103

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

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

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

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

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

    var util = require('util');
    var Trait = require('light-traits').Trait;
    var expect = require('chai').expect;
    var _ = require('lodash');
    function inherits(constructor, parentConstructor, trait, properties) {
      util.inherits(constructor, parentConstructor);
      if (properties !== undefined)
        _.extend(constructor.prototype, properties);
      if (trait !== undefined)
        constructor.prototype = trait.create(constructor.prototype);
    }
    
    function Animal() {}
    Animal.prototype = {
      isAlive: true,
      eat: function (food) {
        console.log("omnomnom, I'm eating: " + food);
      },
      sleep: function () {
        console.log('zzzz');
      },
      die: function () {
        this.isAlive = false;
        console.log("I'm dead");
      }
    };
    
    function CatFamily() {}
    inherits(CatFamily, Animal);
    function DogFamily() {}
    inherits(DogFamily, Animal);
    
    var TMeow = Trait({
      meow: function () {
        console.log('meow meow');
      }
    });
    function Cat() {}
    inherits(Cat, CatFamily, TMeow);
    
    var cat = new Cat();
    cat.meow();
    
    var TBark = Trait({
      bark: function () {
        console.log('woof woof');
      }
    });
    function Dog() {}
    inherits(Dog, DogFamily, TBark);
    
    var dog = new Dog();
    dog.bark();
    
    
    var THunt = Trait({
      huntCount: 0,
      hunt: function () {
        console.log('looking for food', this.huntCount++, 'times');
    
      },
      kill: function (animal) {
        animal.die();
        console.log('I killed animal');
      }
    });
    
    function Tiger() {}
    inherits(Tiger, CatFamily, THunt, {
      roar: function () {
        console.log("roar...roar...");
      }
    });
    
    var tiger = new Tiger();
    expect(tiger).to.be.instanceOf(CatFamily);
    expect(tiger).to.have.property('hunt');
    expect(tiger).to.have.property('kill');
    expect(tiger).to.not.have.property('meow');
    expect(tiger.isAlive).to.be.equal(true);
    tiger.hunt();
    tiger.eat('meat');
    tiger.roar();
    
    function Wolf() {}
    inherits(Wolf, DogFamily, Trait.compose(TBark, THunt));
    
    var wolf = new Wolf();
    expect(wolf).to.be.instanceOf(DogFamily);
    expect(wolf).to.have.property('hunt');
    expect(wolf).to.have.property('kill');
    expect(wolf).to.have.property('bark');
    expect(wolf.isAlive).to.be.equal(true);
    wolf.bark();
    wolf.hunt();
    wolf.hunt();
    wolf.sleep();
    wolf.kill(cat);
    expect(cat.isAlive).to.be.equal(false);
    expect(wolf.huntCount).to.be.equal(2);
  • 相关阅读:
    HDOJ_就这么个烂题总是WA先放这把
    [NYLG-OJ] 77 开灯问题(白书例题)
    [NEUQ-OJ] 1012 SZ斐波拉契数列
    福尔摩斯到某古堡探险
    第n个素数是多少?
    自然数的和之和
    水仙花数
    解决满屏显示问题的css样式:object-fit
    H5新属性audio音频和 video视频的控制
    用indexOf方法来去重
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/7760334.html
Copyright © 2020-2023  润新知