가령 ClassA와 ClassB가 존재하고 ClassB가 ClassA를 상속하고 있다면 실제 JS로 어떻게 구현할가요?
아래에 그럼 간단한 샘플 코드를 첨부하도록 하겠습니다.
<script>
function ClassA()
{
this.a='a';
}
function ClassB()
{
this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
for(var p in objB)document.write(p+"<br>");
</script>
function ClassA()
{
this.a='a';
}
function ClassB()
{
this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
for(var p in objB)document.write(p+"<br>");
</script>
하지만 JS의 원형 상속구조는 Clone(복사) 상속구조가 아닌 Refer(참조)상속입니다.
이런 이유땜에 만약 ClassA인스턴스 맴버변수를 변경하면 ClassB 인스턴스도 변화를 가져오게 됩니다.
<script>
function ClassA()
{
this.a='a';
}
function ClassB()
{
this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
alert(objB.a);
ClassB.prototype.a='changed!!';
alert(objB.a);
</script>
function ClassA()
{
this.a='a';
}
function ClassB()
{
this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
alert(objB.a);
ClassB.prototype.a='changed!!';
alert(objB.a);
</script>
하지만 파생된 클래스에서 맴버변수에 대한 수정은 부모 클래스에는 영향을 주지 않으므로 실제 상속된것과 같은 형태로 표현이 되여집니다. 즉 쓰기 작업은 파생된 클래스에 한해서 진행이 되고 읽기는 부모 클래스( 자식 클래스에서 오버라이딩하지 않았을시)에 한해서 진행이 되여집니다.
또한 파생된 클래스 인스턴스가 하나가 아닌 두개가 존재한다면 두 인스턴스가 동일한 부모 클래스 맴버변수를 참조하게 되므로 실제 비교를 해보면 똑같은 결과가 나옴을 알수 있습니다.
<script>
function ClassA()
{
this.a=function(){alert();};
}
function ClassB()
{
this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
alert(objB1.a==objB2.a);
alert(objB1.b==objB2.b);
</script>
function ClassA()
{
this.a=function(){alert();};
}
function ClassB()
{
this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
alert(objB1.a==objB2.a);
alert(objB1.b==objB2.b);
</script>
아래에 첨부한 코드를 살펴보면 가장 치명적인 문제를 발견할 수 있는데, 보시다 싶이 ClassB의 인스턴스 objB1속의 맴버변수의 값만 변경하였을 뿐인데 objB2의 값까지도 변경이 되여져 있습니다.
<script>
function ClassA()
{
this.a=[];
}
function ClassB()
{
this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
objB1.a.push(1,2,3);
alert(objB2.a);
// 모든 ClassB 인스턴스속의 a값이 모두 변화가 일어났다!!!
</script>
function ClassA()
{
this.a=[];
}
function ClassB()
{
this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
objB1.a.push(1,2,3);
alert(objB2.a);
// 모든 ClassB 인스턴스속의 a값이 모두 변화가 일어났다!!!
</script>
이러한 원인 때문에 위에서 설명드린 방식으로 상속을 구현하는것 보다는 prototype을 이용하여 상속을 구현하면 실제 저희가 원하는 결과를 얻을수 있습니다.
prototype상속은 파생된 클래스의 원형(原型)객체를 부모클래스의 한 인스턴스로 설정하여 상속을 구현하고 있습니다.
사용상 편이를 위하여 Function 객체의 한 메소드로 정의하여 사용합니다.
Function.prototype.Extends = function (parentClass)
{
var Bs = new Function();
Bs.prototype = parentClass.prototype;
this.prototype = new Bs();
this.prototype.Super = parentClass;
this.prototype.constructor = this;
}
{
var Bs = new Function();
Bs.prototype = parentClass.prototype;
this.prototype = new Bs();
this.prototype.Super = parentClass;
this.prototype.constructor = this;
}
2007/11/17 - [분류 전체보기] - Prototype 1.5.0 API
2007/11/14 - [자바 어플리케이션/기타 프레임웍들] - JSValidate - Form Validation Library
2007/09/14 - [자바 어플리케이션/기타 프레임웍들] - Prototype 은 어떻게 DOM에 대한 확장을 하였는가?
2007/09/13 - [자바 어플리케이션/기타 프레임웍들] - prototype 1.5.1.1 Javascript 프레임웍 사용기 - 제1부
2007/02/26 - [자바 어플리케이션/기타 프레임웍들] - Prototype을 위한 퀵 가이드
댓글 없음:
댓글 쓰기