一から勉強させてください( ̄ω ̄;)

最下級エンジニアが日々の学びをアウトプットしていくだけのブログです。

CoffeeScriptでJavaScriptの継承を書き直してみた

以前、JavaScriptの継承についてという記事を書いたのですが、最近Rubyやらなんやらをいじっている影響でCoffeeScriptで書き直したい欲求が出てきました(゚∀゚)

というわけで今回はCoffeeScriptでオブジェクトの継承を書いてみますよー。


ちなみにcoffee→jsのコンパイルですが、以下のようにやりましたー。

npm install -g coffee-script

cd coffeeファイルのある場所
coffee -c ファイル名(◯◯.coffee)


では早速コードのほうを。こちら↓

class Animal
    constructor: (name) ->
        @name = name

    get_name: ->
	console.log(@name)

    breathe: ->
	console.log("ふーふー")

animal = new Animal("あにまる")
animal.get_name() //あにまる
animal.breathe() //ふーふー

class Cat extends Animal
    constructor: (name)->
	super(name)

    cry: ->
	console.log("にゃーにゃー")

cat = new Cat("ねこ")
cat.get_name() //ねこ
cat.breathe() //ふーふー
cat.cry() //にゃーにゃー


んで、吐き出されたjsファイルはこちら。

// Generated by CoffeeScript 1.6.3
(function() {
  var Animal, Cat, animal, cat,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  Animal = (function() {
    function Animal(name) {
      this.name = name;
    }

    Animal.prototype.get_name = function() {
      return console.log(this.name);
    };

    Animal.prototype.breathe = function() {
      return console.log("ふーふー");
    };

    return Animal;

  })();

  animal = new Animal("あにまる");

  animal.get_name();

  animal.breathe();

  Cat = (function(_super) {
    __extends(Cat, _super);

    function Cat(name) {
      Cat.__super__.constructor.call(this, name);
    }

    Cat.prototype.cry = function() {
      return console.log("にゃーにゃー");
    };

    return Cat;

  })(Animal);

  cat = new Cat("ねこ");

  cat.get_name();

  cat.breathe();

  cat.cry();

}).call(this);


吐き出されたjsはなかなかごちゃごちゃしとりますが、coffeeのコード自体はスーパーシンプルに書けました。


ではざっくりと3点ピックアップして、コードを見ていきたいと思います。

・class

まずJavaScriptでは使う事のできなかった禁断のキーワードclassが使えます。(ES6で解禁?)

class Animalって書くだけで実際には

var Animal;
Animal = (function() {
  function Animal() {}
  return Animal;
})();

が吐き出されるみたいですね。ただの自分を返す関数です。


・constructor

たとえば

this.name = name

みたいに自分の名前をセットするような、initializeメソッド的なものを書くにはclassのなかで

constructor: (name) ->
    @name = name

としてやればOK。


function(){ } は ->

this は @

で書けるので楽ですね。


そしてその他のメソッド定義もconstructorの時と同じく

get_name: ->
    処理

breathe: ->
    処理

と書いてやれば、それぞれこのクラスのprototypeのメソッドとして登録されるので、インスタンスから自由に使用可能になります。


・extendsとsuper

いよいよメインの継承の部分です。

普通にjsで書いてたときはCat.prototype = new AnimalやらObject.create(animal)やらやってましたが、CoffeeScriptではextends一発で終了です。クールですね。


そしてsuperも用意してくれているので、こっからクラスの親のprototypeにアクセスできます。

まあ実際に吐き出されてるjsは結構ごちゃごちゃしてますが、、


extendsは__extendsって関数に変換されてparentのprototypeを除くプロパティをコピー。
superはchild.__super__ = parent.prototypeってあるようにparent.prototypeへのアクセス。

になってます。


このあたりは以前書いたJavaScriptでクラスっぽいコードを書く方法とも通ずるものがあって良い勉強になりました。
でもあんだけ苦労してたのがばからしくなりますねw


以上ざっくりでしたが、こんな感じでめっちゃシンプルに書けるCoffeeScript。めっちゃ良いです。

今後もっと勉強して活用していきたいですねー。


小さな事からコツコツと。