728x90

오늘 자바스크립트로 클래스 상속 기능을 이용하려다 문제가 발생해 긴 시간을 고생했기에 다음에 같은 문제가 발생했을 때 대처할 수 있도록 기록해둡니다.


상속받은 클래스에서 부모 클래스의 프로퍼티 변경 시 발생할 수 있는 문제

Unit이란 클래스를 생성하고, 이 클래스를 상속받는 Background라는 클래스와 Elemental이라는 클래스를 만들었다.

Background 클래스는 인스턴스를 하나만 생성하고, Elemental 클래스는 인스턴스를 3개 생성했다. 그리고, 각각 좌표에 해당하는 position 객체의 값을 변경했다. 그런데 Elemental 객체들만 좌표가 모두 동일하게 바뀌는 문제가 발생했다.

당시 Unit 클래스의 설정은 다음과 같았다.

	function Unit() {
		// …생략...

		this.position = {
			"x": 0,
			"y": 0,
			"z": 0
		};
	}
	Unit.prototype = new Object();
	Unit.prototype.constructor = Unit;
	Unit.prototype.classname = "com.cafe24.twilightsh.core.Unit";

그리고, Elemental 클래스는 다음과 같이 Unit 클래스를 상속받았다.

	function Elemental() {
		// …생략...
	}
	Elemental.prototype = new Unit();
	Elemental.prototype.constructor = Elemental;
	Elemental.prototype.classname = "com.cafe24.twilightsh.wizardof.english.Elemental";

좌표를 나타내는 Unit 클래스를 상속 받으므로, Elemental 클래스에는 position 프로퍼티를 따로 설정하지 않고, 바로 다음과 같이 좌표를 설정했다.

			var half = canvas.width / 2;
			var elementalCount = 3;
			for (var i = 0; i < elementalCount; i++) {

				var elemental = new Elemental();
				elemental.position.x = parseInt(half
						+ (Math.random() * half));
				elemental.position.y =  parseInt(Math.random()
						* canvas.height);
				elemental.position.z =  10;

				unitManager.add(elemental);
			}

위와 같이 x, y 좌표를 무작위로 생성하도록 했음에도, 나중에 확인해보면 모든 Elemental 객체의 좌표값이 동일한다.(더 정확히는 마지막에 생성한 Elemental 객체의 좌표와 동일했다)

아무래도 상속받은 position 값을 3개의 인스턴스가 따로 설정되지 않고, 모두 공유하고 있는 듯하다. 무언가 잘못된 것이 분명했다.

해결책

분명 내가 알고 있기로는 상속받은 프로퍼티를 읽기 동작을 할 때는 부모 클래스의 값을 사용하지만, 한 번이라도 프로퍼티를 쓰기 동작을 경우에는 해당 객체에 새로 값을 할당한다는 것이었다. 그리고 이렇게 한 번 할당되면, 그 이후로는 읽기 동작에서도 해당 객체에서 새로 할당된 값을 읽어온다.

그런데 위의 position 값은 이렇게 동작하고 있지 않았다.

여러가지 테스트 끝에 position 프로프티 자체를 새로 할당해보았다.

				var elemental = new Elemental();
				elemental.position = new Position(parseInt(half
						+ (Math.random() * half)), parseInt(Math.random()
						* canvas.height), 10);
				elemental.collider.x = elemental.position.x;
				elemental.collider.y = elemental.position.y;

이렇게 코드를 바꾸고 나서야 정상적으로 모든 인스턴스의 좌표 값이 개별적으로 설정되었다.

문제의 원인

바꾸려는 프로퍼티 값이 부모 클래스 자체의 프로퍼티인지가 중요한 문제의 원인이었다. 즉, Unit의 프로퍼티인 position 자체를 변경하려 한 경우, 상속받은 Elemental 클래스에는 새로운 position값이 할당되고, 이후 성공적으로 position 값을 가렸다(shadows).

하지만, Unit의 position의 프로퍼티인 x,y,z를 변경한 경우에는 Elemntal에 새로운 position 값이 할당되지 않았다.

참고 - 상속받은 프로퍼티의 읽기와 쓰기 동작 원리

‘자바스크립트 완벽 가이드 (데이비드 플래너건 / 인사이트)’ 204쪽의 내용을 참고하면 다음과 같다.

따라서 프로퍼티의 상속은 프로퍼티를 쓸 때가 아닌 읽을 때만 일어난다. 여러분이 만약, 객체 o가 프로토타입에서 상속받은 프로퍼티 p를 설정하려 하면, 이때부터 o에는 새로운 프로퍼티인 p가 만들어진다. 이제 o에는 p라고 이름 붙은 자신만의 프로퍼티가 생기고, 더이상 p의 값을 프로토타입에서 상속받지 않는다. 그리고 자바스크립트는 여러분이 p의 값을 읽으려 할 때, 먼저 o의 프로퍼티들을 살펴본다. 이 때, 자바스크립트는 o에 정의되어 있는 p를 찾으므로 프로토타입 객체를 검색하지 않으며 그곳에 있는 p의 값을 절대 찾지 않는다. 우리는 종종 이것을 o에 있는 프로퍼티 p가 프로토타입 객체에 있는 프로퍼티 p를 ‘가렸다(shdows)’ 혹은 ‘숨겼다(hides)’라고 말한다.


그 다음 페이지의 그림을 보면 더 이해가 잘 되지만, 여기서는 생략하겠습니다...

반응형

+ Recent posts