OOP의특징
- 추상화
- 캡슐화
- 상속
- 다형성
이 글은 상속(Inheritance)에 대한 수업 정리가 될것이지만, 객체지향의 특성상 다른 특징과 함께 학습하는 것이 필수적이다.
상속은 다른 클래스가 가지고 있는 멤버(부모 클래스의 필드, 메소드)들을 새로 작성할 클래스에서 직접 만들지 않고 상속을 받음으로써 새 클래스가 자신의 멤버처럼 사용 할 수 있는기 능이다.
상속은 클래스의 재사용, 연관된 일련의 클래스들에 대한 공통적인 규약 정의를 위함이다.
장점은아래와같다.
- 보다 적은 양의 코드로 새로운 클래스 작성 가능하다는것
- 코드를 공통적으로 관리하기 때문에 코드의 추가 및 변경이 용이하다는것
- 코드의 중복을 제거하여 프로그램의 생산성/유지 보수에 기여
Prototype chain - 사양
Js : JavaScript 는 프로토 타입의 언어이다.
Js가 OOP를 생각하고 만든 언어는 아니지만, OOP가 보편적인 개발론이기 때문에 프로토타입을 활용하여 OOP를 구현하고자 노력하였다. ES6부터 class라는 키워드를 통하여 본격적으로 OOP를 지원하기 시작하였다.
var Human = function(name){
this.name = name;
}
Human.prototype.sleep = function(){};
var steve = new Human('steve');
- Prototype : 모델의 청사진을 만들 때 쓰는 원형객체(Original form)
- constructor :인스턴스가 초기화될 때 실행하는 생성자 함수
- this :함수가 실행될 때, 해당 scope 마다 생성되는 고유한 실행 context (execution context)
new 키워드로 인스턴스를 생성했을 때에는, 해당 인스턴스가 바로 this값이 됨
Ex) Array도 클래스이고, Instance를 만들때 new Array로 생성
var Array = function(location){
[native code]
}
Array.prototype.push = function(){};
Array.prototype.slice = functio(){};
...
var arr = new Array();
그래서 mdn의 문서에 또한 Array.prototype.find() 이런식으로 기재되어 있는 것이다.
var Human = function(name){
this.name = name;
}
Human.prototype.sleep = function(){};
var steve = new Human('steve');
steve.toString();
// [objcet Object]
// 모든 객체에 toString이라는 method 사용 가능
위 객체는 분명 toString이라는 메소드를 정의하지 않았지만, 사용가능하다.
steve 는 Human을 상속받았고, Human은 Object prototype을 상속받았기 때문이다.
이전 콘솔에 찍혔던 steve.__prototype__의 __prototype__에는 Objet라는 prototype이 들어있고 각종 메소드가 이미 구현되어있는 상태로 들어있다.
steve.__prototype__.__prototype__ === Objet.prototype
모든 객체는 상위단계는 Object가 있다. = 모든 객체는 Object를 상속받는다.
배열은 할당이 가능하다. 해당 object로 할당하지 않더라도, prototype을 할당하면 oject와 같이 작동한다.
var MyArray = function(){
}
MyArray.prototype = Array.prototype;
var myarr = new MyArray();
myarr.push(1); //MyArray [1]
그렇다면 상속을 어떻게 구현할것인가?
var Human = function(name){
this.name = name;
}
human.prototype.sleep = function(){};
var steve = new Human('steve');
var Student = function(name){}
Student.prototype.learn = function(){};
var john = new Student('john');
// john.learn();
// john.sleep();//상속을 통한 구현이 가능하다.
방법1 - Deprecated
john.__proto__ = Human.prototype
지금은사용되지 않음
아래코드또한 객체의 참조를 바꾸어버린것이기 때문에 의미가 없다.
Student.prototype = Human.prototype
Student.prototype.learn = funciton(){}
// Student.prototype 과 Human.prototype이 같아진다.
방법2 - Object.create()
Student.prototype = Objcet.create(Human.prototype);
Student.prototype.learn = function(){}
Object.create 는 첫번째 인자로 들어가는 prototype을 기반으로 prototype을 만든다. =>(__prototype__)
하지만 이전에 연결해 두었던(new Human 으로) __prototype__이 증발.
Student.prototype = Object.create(Human.prototype);
Student.prototype.constructor = Student;
Student.prototype.learn = function(){}
이를 해결하기 위해서는 constructor 을 사용해야한다. (Js는 OOP를 위한 언어가 아니였기때문에)
또한 context가 전달되지 않기때문에(this 의 undefined 화) call을 통해 this를 지정해주어야한다.
var Human = function(name){
this.name = name;
}
Human.prototype.sleep = function(){
console.log(this.name + ' is sleeping ...');
}
var steve = new Human('steve');
var Student = function(){
Human.call(this, name); // Human.apply(this, arguments)
//constructor에 this를 전달해주어야함
}
Student.prototype = Object.create(Human.prototype);
Student.prototype.constructor = Student;
Student.prototype.learn = funciton(){};
var john = new Student('john');
john.learn();
john.sleep(); // john is sleeping...
steve instance of Human === true;
john instance of Student === true;
john instance of Human === true;
Class keyword, Super
class Human{
constructor(name){
this.name = name;
}
sleep(){
return 'sleep';
}
}
var steve = new Human('steve');
class Student extends Human{
constructor(name){//자식class와 모양이 같다면 생략 가능
super(name);
//this전달부 super 로 대체
}
sleep(){
return super.sleep();
//상위 메소드 return
// return super.sleep() + 'in the desk';
}
learn(){
}
}
var john = new Student('john');
john.learn();
john.sleep();/sleep in the desk
위에서 prototype chain과 동일함!
하지만 prototype chain보다 훨씬 많이 쓰이게될이다.
OOP인만큼 다형성또한 구현된다.
funciton Human(name){
this.name = name;
}
Human.prototype.sleep = function(){
console.log('zzz')
}
function Student(name){
Human.apply(this, arguments);
}
Student.prototype.sleep = funciton(){
Human.prototype.sleep.apply(this);
//뒤개의 sleep method가 같은 context를 공유한다...
console.log('자면안되!!!');
}
suepr의 속성 삭제 - delete 키워드 사용불가
class Base{
constructor(){}
foo(){}
}
class Derived {
constructor(){}
delete(){
delete super.foo();
}
}
//ReferenceError 발생
new Derived().delete();
super.prop사용
var obj1 = {
method1() {
console.log("method 1");
}
}
var obj2 = {
method2() {
super.method1();
}
}
Object.setPrototypeOf(obj2, obj1);
obj2.method2(); // "method 1"
'창고(2021년 이전)' 카테고리의 다른 글
[프로젝트 회고] Dedicats Server 4주 프로젝트 (0) | 2020.03.02 |
---|---|
React_1 : 리액트, 리액트 프로젝트 시작하기 (0) | 2019.12.12 |
[Java] Comparator (0) | 2019.11.16 |
[자료구조] Linked List, Graph, Tree, Binary Search Tree, Hash Table (0) | 2019.11.15 |
[자료구조] Stack & Queue (0) | 2019.11.15 |