24. Polymorphism

Polymorphism

Polymorphism은 여러가지 다른 방법으로 하나의 메세지에 응답하는 다른 클라스들의 능력을 이야기한다. 어떤 메세지는 일반적으로 그 내면의 의미를 담고있고, 그것이 각각 클래스의 책임으로서 그 의미에 적절한 방법으로 대응하기 위한것이다.

예를들어 value라는 메세지는 “이 오브젝트의 적절한 값을 주세요’라는 의미를 가진다.

그 value의 방법은 다음의 클라스에 정해져 있다.
Function : this.value(args)
Object : this.value()
Ref : this.value

그렇다면 클래스가 정의된 방법을 보자.
 여기 클라스 Object에 있는 value방법이 있다.
value { ^this }
위는 단순히 그것을 return 하라는 명령이다. 모든 클래스들은 클라스 Object에 의해 전해져 내려오므로, 이 뜻을 클라스가 value를 무시하지 않는 한 그 오브젝트는 그 자신을 return시킴으로서 value 에 응답한다. 

5.postln; // posts itself
5.value.postln; // value returns itself
‘a symbol’.postln;
‘a symbol’.value.postln;
[1,2,3].value.postln;
//etc..

클라스 Function에서 value방법은 기본으로 들어간다.
 value { arg … args; 
  _FunctionValue 
  // evaluate a function with args
  ^this.primitiveFailed 
 }

_FunctionValue 는 C code기본으로 이것이 무엇을 하는지는 이것만 보아서는 알수 없다. 그러나 그것이 하는일은 그 function을 처리하고 그 결과를 보내는 일이다.
{ 5.squared }.postln; // posts Instance of Function
{ 5.squared }.value.postln; // posts 25

Ref 클라스는 오브젝트의 간접적인 reference을 만드는 방법을 제공한다. 이는 reference 에 의해 value 를 통과하도록 쓰일 수 있다. Ref Obkect들은 하나의 instance variable ‘value’를 갖는다. 그 ‘value’방법은 그 instance variable의 ‘value’의 값을 보낸다. 다음 예제를 보자.
Ref : AbstractFunction 
{
 var <>value;
 *new { arg thing; ^super.new.value_(thing) }
 set { arg thing; value = thing }
 get { ^value }
 dereference { ^value }
 asRef { ^this }

 //behave like a stream
 next { ^value }
 embedInStream { arg inval;
  ^this.value.embedInStream(inval)
 }

 printOn { arg stream;
  stream << “`(” << value << “)”;
 }
 storeOn { arg stream;
  stream << “`(” <<< value << “)”;
 }
}
****^의 의미는 return. class에서 ^가 없으면 instance를 return한다. 
****this의 의미는 instance(서두에 instance method가 있는 경우)또는 class (서두에 classMethod가 있는 경우)
Ref.new(123).postln;//ref를 내보낸다.
Ref.new(123).value.postln;//ref의 값을 내보낸다.

Ref는 또한 dereference라는 메세지를 만든다. dereference는 value method가 하는 일과 다르지 않은 instance variable로 value를 보낸다. 그럼 이것은 왜 필요할까? 그것은 어떻게 다른 class들이 dereference에 응답하는가에 의해 설명된다. dereference메세지는 “당신을 포함하고 있는 어떤 Ref든 없애라” 라는 메세지를 의미한다. class Object에서 dereference는 그 object자체를 보낸다. 이는 value 메세지와 같은 양상이다. 차이점은 다른 class들이 이 방법을 취하하지 않는다는 것이다. 따라서 어떤 Function의 dereference는 여전히 Function이다.

Object : this.dereference()
Ref : this.dereference()

5.value.postln;  
{ 5.squared }.value.postln;  
Ref.new(123).value.postln;

5.dereference.postln;  
{ 5.squared }.dereference.postln;//여기를 주목. 위에서는 25를 출력했다.  
Ref.new(123).dereference.postln;//dereference의 값을 내보낸다. ref를 보내는것이 아니다.


또 다른 예제로는 play가 있다. 
{ PinkNoise.ar(0.1) }.play; // Function

( // AppClock
var w, r;
w = GUI.window.new(“trem”, Rect(512, 256, 360, 130));
w.front;
r = Routine({ arg appClockTime;
  [“AppClock has been playing for secs:”,appClockTime].postln;
  60.do({ arg i;
  0.05.yield;
  w.bounds = w.bounds.moveBy(10.rand2, 10.rand2);
  w.alpha = cos(i*0.1pi)*0.5+0.5;
  });
  1.yield;
  w.close;
});
AppClock.play(r);
)

( // SynthDef
x = SynthDef(“Help-SynthDef”, 
 { arg out=0;
  Out.ar(out, PinkNoise.ar(0.1))
 }).play;
)

Pbind(degree, Pseq([0, 1, 2, 3],inf)).play; // Pattern

reference: SC3메뉴얼



Leave a Comment.

This site uses Akismet to reduce spam. Learn how your comment data is processed.