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;
)
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메뉴얼