객체지향을 간단하게 이해하기...!

jae·2022년 8월 17일
0
post-thumbnail

코드 공부를 막 시작하며 인터넷으로 이것저것 지식을 마구 주워먹..배울때
객체지향 프로그래밍이 중요하다는 이야기를 많이 봤었다..!

함수형 프로그래밍을 다루고 있어서 클래스라고 하면 html에 css 넣어주는 클래스네임...을 먼저 하는 사람이기에 class로 하는 객체지향 프로그래밍을 이해할 필요가...있지....

클래스를 네이버에 쳐보면...?

예전에 붕어빵틀과 붕어빵들로 비교를 해서 설명해주었던게 기억이 나는데 못찾겠다...
아무튼 대략적으로 기억나는 건

클래스는 붕어빵 틀! 객체(인스턴스)는 클래스로 찍어낸 붕어빵
내가 팥이나 슈크림,치즈 등등 어떤 재료(변수나 값)를 넣느냐에 따라 다른 맛의 붕어빵이 나오지만 붕어빵 틀로 찍어낸 붕어빵이라는 것은 변함이 없다.

어떤 붕어빵틀을 만들 것인지 내가 설계를 하고!
뭘 넣을지 재료를 선택해서 붕어빵 틀로 붕어빵을 만드는 것!
아무튼 이렇게 대략적인 이해를 하고 있으니 대략이 아닌 자세히 공부해본다

constructor

contstructor 문법의 용도

  • 객체를 복사하고 싶을 때 사용하는 것(오브젝트 생성 기계)
  • this(새로 생성될 object(인스턴스))가 필요함
function con(){
this.taste="redbean"
this.count=5 // 새로 생성될 것의 오브젝트의 키와 값을 지정하는 것
}
let bbang= new con()

bbang(this)의 title은 boong으로 해주세요! 라고 선언한 것.
이렇게 값을 만들기 위해서 this를 사용하고 new를 이용해 새롭게 남아주면 된다.
이걸 con이 가지고 있는 키와 값들 즉 속성을 상속 받는 것

그리고 동일하게 동일 키에 다른 값을 넣고 싶은 것이라면
파라미터를 활용하면 된다.

function con(TastePick,CountPick){
	this.taste=TastePick
	this.count=CountPick
	this.price=function(){
	this.count*500
	}
}
let bbang= new con(pizza,10)
/// bbang.taste 는 pizza bbang.count는 10 된다
/// bbang.price는 500에 10개를 곱하여 5000이 나온다

그리고 추가적으로 콜백으로 함수안에서 추가적인 계산을 하거나 추가적인 기능을 넣을수도 있다.

Prototype

  • 원형

붕어빵틀인 class의 내용을 상속받은 붕어빵인 변수들..
그 상속을 구현하는 문법이다.

function con(TastePick,CountPick){
	this.taste=TastePick
	this.count=CountPick
	this.price=function(){
	this.count*500
	}
}
let bbang= new con(pizza,10)

여기서 만든 con에는 [[prototype]] 라는 은닉 속성이 있다.

  • _ proto 라는 속성으로 참조할 수 있지만 모든 브라우저에서 동작하는 것은 아니기에 사용은 삼가하는게 좋다..!
    - bbang.
    proto _ 를 확인하면 붕어빵틀의 prototype을 확인할수 있음

con.prototype을 확인해보면 오브젝트(객체)가 나오는데

function con(TastePick,CountPick){
	this.taste=TastePick
	this.count=CountPick
	this.price=function(){
	this.count*500
	}
}
con.prototype.type="bread"

let bbang= new con(pizza,10)

이렇게 prototype을 사용한다면
con 내부에 type이라는 키가 없어도 bbang.type을 확인하면 bread라고 확인할 수 있다..!

왜 그렇게 될까...?
인스턴스(bbang)의 클래스(con)에 type이라는 키의 값을 찾으러 올라간다.
인스턴스 자체에 type이 없으면 스코프 체인이 일어나는 거처럼
프로토타입 체인이 생성된다.

프로토타입 체인

  • 참조할 때 만약 찾을 수 없다면 undefined가 반환됨
  • 할당할 때 찾을 값이 객체에 존재하면 값이 바뀜
  • 내장함수도 동일하게 동작하는데 여기에 없으면 올라가서 찾고 없으면 또 올라가고를 반복한다.
    array.prototype를 확인해보면 메소드들을 확인해볼 수 있다.
    MDN에 메소드를 검색해보면 prototype이라는 단어를 자주 볼수 있는데
    array 프로토타입에 메소드가 포함되어있다는 뜻인 것이다.

constructor와 Prototype의 차이

똑같은 상속기능인 건데 왜 따로 쓰는 것일까??
자식들이 값을 직접적으로 가지게 하고 싶으면 constructor를 쓰고
부모가 가지고 있어서 올라와서 직접 확인한 다음에 가져가게 하고 싶으면 prototype을 쓰면 된다. 보통은 상속할수 있는 함수에만 생성된다.

class

es6 방식으로 구현하는 constuctor

class 붕어빵틀{
	constructor(){
    this.taste="redbean"
    }
}

let 붕어빵= New 붕어빵틀()
//콘솔로 붕어빵을 확인하면 '붕어빵틀{taste:"reabean"}' 이 나옴

함수도 동일하게 constructort안에 넣을 수 있는데...
만약 constructor가 아닌 외부에 this를 이용하여 키를 입력한다면???

class 붕어빵틀{
	constructor(){
    this.taste="redbean"
    }
    this.price=500
}

let 붕어빵= New 붕어빵틀()

이라하면 붕어빵을 확인하면 price를 확인할수 없다.
constructor외부에 price를 추가하였기때문에
붕어빵틀의 prototype에 price가 추가될뿐이고 붕어빵 자체에는 추가가 되지않는다.
그래서 붕어빵 자체에 키값이 추가되길 원한다면 constructor에 입력을 해야하고
붕어빵의 원형 즉 붕어빵틀에서 확인하길 원한다면 이렇게 숨겨둘수도 있다.

  • 붕어빵에 _ proto _로 확인하면 전체 확인할수는 있다...
  • object.getPrototypeOf(붕어빵)
    이런 키워드로 확인한다면 붕어빵틀의 prototype을 확인할 수 있다..
function 오븐() {}
function 붕어빵틀() {}
let 빵 = new 오븐();
console.log(Object.getPrototypeOf(빵)); // 오븐.prototype
Object.setPrototypeOf(빵, 붕어빵틀.prototype);
console.log(Object.getPrototypeOf(빵)); // 붕어빵.prototype
  • Object.setPrototypeOf(붕어빵, .prototype);
    이렇게 set을 이용하면 object.getPrototypeOf(붕어빵)을 입력하면 붕어빵틀이 아닌 오븐이라는 다른 특정객체의 프로토타입을 붕어빵으로 재할당한다

extends

클래스를 복사하는 방법
기존 class에 몇가지 기능이 추가된 class를 만드는 것

class 붕어빵틀{
 constructor(내용물){
  this.종류=내용물
 }
}

let 붕어빵= New 붕어빵틀("팥붕")

이렇게 붕어빵틀이라는 클래스의 내용을 가지고 몇가지가 추가된
유사한 클래스를 만들고 싶다면 똑같이 하드코딩해서 복사해도 되지만 extends라는 것을 쓰면 기존의 붕어빵틀 클래스에 있던 속성들을 가져오며 기능추가도 가능하다.

class 풀빵틀 extends 붕어빵틀{
	constructor(내용물){
  	 super(내용물);
 	 this.모양= "꽃"
 	}
}
let 풀빵= New 풀빵틀("팥")
// 풀빵을 콘솔로 확인하면 모양: "꽃" 내용물:"팥"

this를 그냥 사용하지 못하고 super()를 사용해야하는데
이 super()는 물려받는 기존 붕어빵틀 클래스에 있던 내용을 그대로 가져오게한다.
그리고 기존 클래스에 파라미터 매개변수가 있기때문에
동일하게 풀빵틀에도 파라미터를 동일하게 맞춰주어야한다.
입력하지 않으면 매개변수를 쓸수 없어서 종류의 값을 넣을수가 없다...

super()의 다른 기능!

class 붕어빵틀{
 constructor(내용물){
  this.종류=내용물
 }
 한정판(){
 	console.log("10개")
 }
}

let 붕어빵= New 붕어빵틀("팥붕")

class 풀빵틀 extends 붕어빵틀{
	constructor(내용물){
  	 super(내용물);
 	 this.모양= "꽃"
 	}
    한정판(){
	 console.log("5개")
 	}
}
let 풀빵= New 풀빵틀("팥")

기존에는 constructor의 외부에 값을 넣으면 상속받은 곳 prototype에서는 외부의 값을 확인할수 없었다.
하지만 super()를 쓰게 되면 construtor 외부의 값도 확인할수가 있다!

이건 super가 상위 요소의 내용을 전체 다 복사해오는 것이라 그렇다.
만약 붕어빵틀과 풀빵틀에 동일한 함수명이나 변수명을 쓴다면
즉 풀빵틀.한정판을 확인하면 풀빵틀에만 있는 함수 즉 5개가 확인이 된다...

class 붕어빵틀{
 constructor(내용물){
  this.종류=내용물
 }
한정판(){
 	console.log("10개")
 }
}

let 붕어빵= New 붕어빵틀("팥붕")

class 풀빵틀 extends 붕어빵틀{
	constructor(내용물){
  	 super(내용물); //붕어빵틀의 constructor
 	 this.모양= "꽃"
 	}
    한정판(){
	 console.log("5개")
     super.한정판() //붕어빵틀의 prototype
 	}
}
let 풀빵= New 풀빵틀("팥")

이렇게 super를 constructor 외부에 쓰면 붕어빵틀의 한정판을 가져온다
이렇게 된다면 풀빵틀.한정판()을 확인하면
콘솔에 5개와 10개 이렇게 두개가 찍히게 된다...


함수형을 위주로 해온 나에겐 조금은 생소하고 어려운 개념이다 ㅠㅠ
이렇게 간단하게 생각해보려고 하는데도 몇시간째 붙잡고 있었는지 ㅠㅠ
하지만 레퍼런스 코드를 찾다보면 많은 객체지향형 코드들이 나온다.
이렇게 문법적으로 간단하게나마 원리를 이해하고 나니
궁금해지는게 더 많다는게 문제...ㅎ

0개의 댓글