자바스크립트 추상 클래스 구현









- 추상클래스 분류:

Animal(동물), Felidae(고양이과), Canidae(개과)


- 일반클래스(구현클래스) 분류:

하마, 사자, 고양이, 호랑이, 늑대, 개




1. 각 단어에 대한 의미


추상: 덜 구체화된 무엇.

객체: 상태(Attribute)와 행동(Method)을 가진 것.

클래스: 객체 생성을 위한 일종의 도면(설계도, 청사진).

초기화: 정의된 클래스를 이용하여 객체를 생성(인스턴스 생성)하는 것.




2. 제약사항(C# 기준)


1. 스스로의(추상클래스 자신) 객체를 가질 수 없다.

2. 선언된 추상클래스의 추상 메서드는 상속받은 일반클래스(구현클래스)에서 반드시 전부 구현되어야 한다.

3. 클래스(추상)가 메서드(추상)를 반드시 포함하지 않더라도 abstract 키워드가 있다면 추상클래스가 된다.

4. 일반 속성(Attribute) 및 메서드(Method)를 정의할 수 있다.




3. 추상클래스(Animal(동물))는 왜 객체를 가질 수 없는가?


위 "1. 단어에 대한 의미"에서 "객체"란 상태(Attribute)와 행동(Method)을 가진것이라 이미 언급하였다.


또한, "추상"이란 덜 구체화된 무엇을 뜻하며, 이는 "객체"가 반드시 가져야할 상태(Attribute)와 행동(Method(구현되지 않은 추상 메서드))을 갖지 못했다는 의미로 볼 수 있다.


즉, 이를 요약하면, "넌 너무 추상적인 클래스(설계도, 청사진)를 가졌으니 객체를 만들 수 없다!!!(인용)" 라는 의미로 보면 될듯하다.




4. 자바스크립트 추상 클래스 구현


/**
 * 
 * 추상클래스(ABoard)가 가진 기본적인(C# 기준) "제약"과 같이 자기 자신의 객체를 가질 수 없다.
*/
var ABoard = (function(){
	
	var aBoard = function(){
		
		this.id = '';
		this.name = '';
		
		// 자기 자신의 객체 생성을 막기 위한 추가 소스
		if (this.constructor === aBoard){
			throw new Error('정의된 추상클래스는 자기 자신의 객체를 가질 수 없습니다.');
		}
		else{
			return this;
		}		
	};
	
	var prototype_members = {
		
		getId: function(){
			return this.id;
		},
		setId: function(id){
			this.id = id;
			return this;
		},
		getName: function(){
			return this.name;
		},
		setName: function(name){
			this.name = name;
			return this;
		},		        	
		view: function(){
		},
		write: function(){
		}
	};
	
	for (var n in prototype_members) aBoard.prototype[n] = prototype_members[n];
	
	// 기존 OOP 언어의 abstract "키워드"와 같이 아래 처럼 추상메서드를 선언이 가능하다.
	aBoard.prototype.view.isabstract = true;
	aBoard.prototype.write.isabstract = true;
	
	return aBoard;
	
})();

// 상속받은 추상 메소드를 구현한다.(자유게시판)
var Free = abstractInherit(ABoard, {
	// Repository
	view: function(){
		alert(this.id + '님의 이름은 ' + this.name + '입니다.');	
	},
	write: function(){
		alert('write ok!!!');
		return this;
	}
});	


// 상속받은 추상 메소드를 구현한다.(QA게시판)
var QA = abstractInherit(ABoard, {
	// Repository
	view: function(){
		alert(this.name + '님 안녕하세요!!!!');	
	},
	write: function(){
		alert('write ok!!!');
		return this;
	}
});			       	        

// 일반클래스(구현클래스)에 정의된 추상클래스 상속함수
function abstractInherit(_abstract, opt){
	
	
	var o = {};
	
	// 추상 클래스의 추상 메서드 카운트
	var abstractMethodCount = 0;
	// 일반 클래스의 추상 메서드 구현 카운트
	var classMethodCount = 0;
	
	var F = function(){};
	
	for (var n in _abstract.prototype){
		F.prototype[n] = _abstract.prototype[n];
	}

	var $F = _abstract.call(new F());
	
	
	for (var n in $F){
		
		o[n] = $F[n];
		if (opt[n]) o[n] = opt[n];
		
		if ($F[n].isabstract) abstractMethodCount++;
		if ($F[n].isabstract && opt[n]) classMethodCount++;
	}
	
	if (abstractMethodCount !== classMethodCount){
		// 일반 클래스(구현 클래스)에 정의된 추상 메서드의 구현 메서드가 없을떄..
		throw new Error('상속된 추상 메서드가 구현(모두)되지 않았습니다.');
		return {};
	}
	else {
		return o;
	}
}

Free.setId('yanione1').setName('전성균1').write().view();
QA.setId('yanione2').setName('전성균2').write().view(); 





예제 실행 URL:

http://jsfiddle.net/jeonseounggyun/Cavbe/



출처 및 참고 URL:


1. 추상 클래스의 존재 이유

http://itewbm.tistory.com/24


2. 왜 추상 클래스를 사용하게 될까?

http://mrtint.tistory.com/678