https://www.youtube.com/watch?v=E9NZ0YEZrYU
value context(메모리 주소와 관계없이 값이 같으면 같은 것)
vs
identifier context(메모리 주소가 다르면 값이 같아도 다른 것)
객체지향은 indentifier context로 개발해야하고, 함수형은 value context 기반으로 개발해야함
const a = {
a: 3,
b: 5,
};
const b = {
a: 3,
b: 5,
};
console.log(a === b); //false (1)
console.log(JSON.stringfy(a) === JSON.stringfy(b));//true (2)
(1)이 indentifier context의 대표적인 예
(2)가 value context의 예 -> 값 비교를 하는 순간 객체지향은 깨졌다고 보면 된다.
여기서 질문
Q. 그러면 단순히 숫자를 받아오는 경우에는 값으로 받아야할텐데 이럴땐 어떻게 객체지향을 쓰는가?
A. new Count 3 이런식으로 받는 것
-> 생성자에서 받아와야하네,,
const Worker = class{
run(){
console.log("working")
}
print(){
this.run();
}
};
const HardWorker = class extends Worker{
run(){//오버라이딩
console.log("hardWorking")
}
};
const worker = new HardWorker();
console.log(worker instanceof Worker);//true -> 자식은 부모를 대체할 수 있다.
worker.print();
다형성의 대체가능성 : 자식(확장된 클래스)은 부모(대상 클래스)를 대체할 수 있지만, 부모는 자식을 대체할 수 없다.
내적 일관성 : 어떤 경우에도 태어났을때의 원본 클래스를 유지하려는 성질
즉, 다형성은 대체가능성 + 내적 일관성
worker.print()의 결과는? worker가 HardWorker로 태어났기 때문에 this는 HardWorker라서 hardWorking으로 출력하기로 합의한 것이 객체지향점의 특징
언어마다 대체가능성과 내적일관성을 구현하는 방식은 다름
js는 프로토타입을 사용
프로토타입 체인 : 본인 먼저 찾아보고 계속 타고가서 찾음. 상속받을때, 가장
A instanceof B
worker instanceof HardWorker 가능
worker instanceof Worker 가능 (타고타고 올라가니까)
즉 자바스크립트는 프로토타입을 통해 대체가능성, 내적일관성을 유지.
각 언어마다 이 두가지를 어떤 것을 통하든 유지하려고 노력함
자바스크립트는 객체지향 언어인가? YES. polymorphism 성립하기 때문에
하지만, 객체지향의 특성을 띄게 코딩을 하는 것은 다른 문제이다.
const EssentialObject = class{
#name = ""; //hide state
#screen = null; //hide state
constructor(name){
this.#name = name;
}
camouflage(){
this.#screen = (Math.random() * 10).toString(16).replace(".", "")
}
get name(){
return this.#screen || this.#name; //encapsulation
}
};
- 객체지향에서 특징 : 속성은 private. 모든 속성이 외부에 노출되지 않는다.
상세 이유 : 객체지향은 메모리의 참조로 움직여야하는데 속성이 공개되는 순간 속성을 값으로 취득하게되고, 값으로 쓰게되면 값 컨텍스트가 만연해지고 객체지향이 무너짐. private가 아닌 변수가 있다면 객체지향이 아님
- 객체지향의 특징 : 메소드는 반드시 캡슐화되어있는 상태로 제공되어야함
1+2 => Isolation of change. 변화에 대한 격리를 이룰 수 있다.
문제예시 | 수정후 |
---|---|
생물을 숨을 쉰다, 다리로 이동한다로 추상해버리면 고래, 독수리는 해당되지 못함. 업캐스팅을 못하게됨 -> -> 인터페이스를 두개로 분리한다. -> ISP
해결책2 : 인터페이스를 사용하는 방법. 처음부터 인터페이스를 3개로 분리하여 객체를 as 아빠, as 엄마로 두어 사용한다.
DIP(Dependency Inversion) : 다운캐스팅금지
: ex if this instance of ChildA
Q. 다운캐스팅은 어떻게 안할수있나?
A. 다운캐스팅을 안하는 것은 SOLID 원칙이 모두 지켜졌을때 가능하기 때문에 매우 어려움
const Worker = class{
run(){
console.log("working")
}
print(){
this.run();
}
};
const HardWorker = class extends Worker{
run({
console.log("hardWorking")
}
};
const Manager = class{
#workers;
constructor(...workers) {
if(workers.every(w=>w instanceof Worker)) this.#workers = workers;
else throw "invalid workers";
}
doWork(){
this.#workers.forEach(w=>w.run())
}
};
const manager = new Manager(new Worker(), new HardWorker());
manager.doWork();