Rev. 2.73

Prototype 1.6.0 RC0 버전이 새롭게 갱신되었습니다.(1.6.0 RC1이 아닙니다.) 모바일 사파리 브라우저 검출부분과 지난번에 소개했던 원인불명의 IE오류 등이 수정되었습니다. 지금까지 Prototype은 기초적인 클래스 생성을 Class.create 메서드를 통해 지원하였습니다. 이 패치버전 이후부터 새로운 형태의 클래스를 다룰 수 있습니다. 이전 버전에서의 클래스 생성 그리고 그 이후의 생성방법을 구분한 예문을 살펴봅시다.

지금까지 일반적으로 사용하던 클래스 예제는 아래와 같습니다. 클래스를 생성할 때마다 자동으로 initialize 함수가 실행되는 구조입니다. Pirate클래스에서 Object.extend 메서드로 Person 클래스를 확장하고 있습니다.

var Person = Class.create();
Person.prototype = {
  initialize: function(name) {
    this.name = name;
  },
  say: function(message) {
    return this.name + ': ' + message;
  }
};

var guy = new Person('Miro');
guy.say('hi');
// -> "Miro: hi"

var Pirate = Class.create();
// inherit from Person class:
Pirate.prototype = Object.extend(new Person(), {
  // redefine the speak method
  say: function(message) {
    return this.name + ': ' + message + ', yarr!';
  }
});

var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"

아래는 새버전에서 사용되는 조금 더 진보된 클래스 생성방법 예제입니다.

// properties are directly passed to `create` method
var Person = Class.create({
  initialize: function(name) {
    this.name = name;
  },
  say: function(message) {
    return this.name + ': ' + message;
  }
});

// when subclassing, specify the class you want to inherit from
var Pirate = Class.create(Person, {
  // redefine the speak method
  say: function($super, message) {
    return $super(message) + ', yarr!';
  }
});

var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"

Object.extend와 Person.prototype을 생략한 것을 알 수 있으며 조금 생소한 $super 아규먼트를 볼 수 있습니다. $super는 오버라이딩 되지않는 원본 메서드로부터 값을 호출하는 능력을 가집니다. 또 다른 클래스 예문을 살펴봅시다.

var Logger = Class.create({
  initialize: function() { },
  log: [],
  write: function(message) {
    this.log.push(message);
  }
});

var logger = new Logger;
logger.log; // -> []
logger.write('foo');
logger.write('bar');
logger.log; // -> ['foo', 'bar']

새로운 클래스를 만들고 배열에 들어있는 내용을 출력했습니다. 그러나 아래처럼 또 다른 Logger 인스턴스가 있다면 어떻게 될까요?

var logger2 = new Logger;
logger2.log; // -> ['foo', 'bar']

네, '쉣'입니다. 비어있지 않은 값을 그대로 반환하죠. 그래서 initialize에는 클래스가 가진 변수를 초기화하는 코드가 있어야합니다. 아래와 같은 모습이겠군요

var Logger = Class.create({
  initialize: function() {
    // this is the right way to do it:
    this.log = [];
  },
  write: function(message) {
    this.log.push(message);
  }
});

그리고 아래처럼 클래스를 확장하는 것이 매우 단조롭습니다.

Pirate.allHandsOnDeck = function(n) {
  var voices = [];
  n.times(function(i) {
    voices.push(new Pirate('Sea dog').say(i + 1));
  });
  return voices;
}

Pirate.allHandsOnDeck(3);
// -> ["Sea dog: 1, yarr!", "Sea dog: 2, yarr!", "Sea dog: 3, yarr!"]

이렇게 생성된 클래스들은 아래와 같은 특별한 프로퍼티를 가지고 있습니다.

Person.superclass // -> null
Person.subclasses.length // -> 1
Person.subclasses.first() == Pirate // -> true
Pirate.superclass == Person // -> true

클래스에 메서드를 추가하려면 Class#addMethods를 사용해야 합니다.

var john = new Pirate('Long John');
john.sleep();
// -> ERROR: sleep is not a method

// every person should be able to sleep, not just pirates!
Person.addMethods({
  sleep: function() {
    return this.say('ZzZ');
  }
});

john.sleep();
// -> "Long John: ZzZ, yarr!"

Comments

Got something to add? You can just leave a comment.

Your Reaction Time!

captcha

avatar