본문 바로가기

JavaScript/React

11. 합성 vs 상속

합성과 상속이란?

객체지향에서 기능 재사용을 위해 사용하는 대표적인 기법이다.

 

상속(Inheritance)?

부모클래스가 구현해둔 무언가를 자식클래스가 상속(extends)해서 무언가를 구현 하는 방법으로 객체 지향 프로그래밍(OOP)에서 많이 사용하며, 자식클래스는 부모 클래스에 정의해둔 field나 method를 그대로 받아서 사용할 수 있다. 내용을 추가(혹은 확장)해서 사용하는 것도 가능하다.

 

class Vehicle{
  constructor(name, type){
 	 this.name = name;
     this.type = type; 
  }
  getName(){ return this.name; }
  getType(){ return this.type; }
}

class Car extends Vehicle{
  constructor(name){
    super(name, 'car');
  }
  getName(){
  	return 'It is a car: ' + super.getName();
  }
}
let car = new Car('Tico');
console.log(car.getName()); // It is a car: Tico
console.log(car.getType()); // car

Vehicle이라는 클래스를 정의했다. 이를 Car라는 클래스가 상속 받았으니까 이제 Car는 Vehicle의 field와 method를 사용할 수 있다.

 

constructor에서 super는 부모 클래스를 가르킨다. super(name, 'car'); 을 적어줌으로 인해서 class Car는 (name)만 파라미터로 받고, type은 'car'로 고정되었다.

그러면서 getName은 새롭게 정의해줬다. getType() 메서드는 부모 클래스에서 쓴 고대로 사용하려고 그냥 두었다.

let car = new Car('Tico')를 통해서 객체를 만들어줬고 이 객체에서 getName()은 "It is a car: Tico", getType()은 "car"가 콘솔에 찍힌다.

 

이를 상속이라 부른다.

 

 

  • 클래스 기반 언어와 프로토타입 기반 언어

    객체지향 언어는 상속에 따라 크게 두 가지로 나눌 수 있다. - 클래스 기반 언어 : Java, C++, Python, Ruby ... - 프로토타입 기반 언어 : Javascript, JScript, ActionScript ...

    클래스 기반 언어는 클래스를 활용해서 객체를 생성하는 반면 프로토 타입 기반 언어는 클래스라는 개념 없이, 객체에서 객체를 바로 상속하도록 한다.

     

 

 

참고

자바스크립트 - 상속
상속이란 반복적인 코드를 작성하지 않고 코드를 재 사용하는 방법을 의미합니다.코드를 재 사용함으로써 소프트웨어 개발기간과 시간을 단축할 수 있습니다. 객체지향 언어는 상속에 따라서 크게 두 가지로 나눌 수 있습니다. 클래스 기반 언어: Java, Python, Ruby, C++, C# 프로토타입 기반 언어: Javascript, JScript, ActionScript 클래스 기반언어에서 클래스는 객체의 형식이 정의되어 있고, 클래스를 활용하여 객체(Instance) 를 생성합니다.

 

 

합성?

서로 다른 객체를 여러 개 붙여서 새로운 객체를 구성한다. 상속과는 다르게 융통적으로 클래스를 합성할 수 있다.

 

컴포넌트에서 다른 컴포넌트 담기

예를들어 컴포넌트로 Dialog나 Sidebar를 만든다고 했을 때, 일반적으로 이런 컴포넌트는 '재사용'을 많이 한다. 그러나 안에 내용을 어떻게 그려줘야할지 미리 알지 못한다.

 

이런 컴포넌트에선 children prop를 사용해서 자식 엘리먼트에 그대로 전달하는 것이 좋다.

예제

function Border(props){
  return(
  	<div> <span>합성 될 컴포넌트입니다</span>
  		{props.children}
 	</div>
  );
}

Boarder 컴포넌트. 이렇게 하면 JSX에서 children을 내장해서 넘겨줄 수 있다.

 

function WelcomeDialog() {
	return(
    	<div>
        	<Border> // Borderd()의 props값을 그대로 전달받았음
           		<h1 className="Dialog-title"> Welcome </h1>
                <p className="Dialog-message"> Than you for visiting our spacecraft! </p>
            </Border>
            <Border> // Border()의 props값을 그대로 전달받았음
            	<h1 className="Dialog-title"> Hi 안녕! </h1>
            </Border>
        </div>
        )
}

ReactDOM.render(
	<WelcomeDialog />,
    document.getElementById('root')
);

FancyBoarder을 받아 WelcomeDialog()에 사용한다.

 

 

 

쉽게 말해 은 자리를 비워두고 나중에 추가하는 구멍이라고 볼 수 있다.

function Border(props){
	return(
		<div>
		  <span>합성 될 컴포넌트입니다</span>
			┌────────────┐ 
			{props.children}
		        └────────────┘	자리염~ 친구올거에요~
		</div>
	);
}

 

 

여러 개의 구멍이 필요한 경우

흔하진 않지만 종종 컴포넌트의 여러 개의 "구멍"이 필요할 수도 있는데, 그러면 children대신 자기만의 고유한 방식으로 지정할 수 있도록 되어있다.

function Contacts() {
  return <div className="Contacts" />;
}

function Chat() {
  return <div className="Chat" />;
}

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left"> // css에서 float : left로 띄움.
        {props.left} //구멍1
      </div>
      <div className="SplitPane-right"> // css에서 float : right로 띄움
        {props.right} //구멍 2
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane left={	<Contacts /> }  //CSS에서 background-color: lightblue로 지정
	right={ <Chat /> }     //CSS에서 background-color: pink로 지정
	/>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

 

 

 

합성? 상속?

 

  • 합성을 사용한 코드를 변경하는 것이 상속을 사용한 코드를 변경하는 것보다 노력이 덜 든다.
  • 상속을 사용한 코드는 일반적으로 합성을 사용한 코드보다 더 빨리 동작한다.

 

Facebook에서 수천 개의 컴포넌트를 쓰고 있지만, 상속으로 구현한 사례는 없다. 아마 둘의 작동 속도가 큰 차이가 없는 게 아닐까...

앞선 예시를 봐도 합성으로 만드는 게 더 직관적으로 알아보기가 쉽다.

 

 

참고

상속 vs 합성
클래스의 인스턴스를 내장 속성으로 정의하고, 인스턴스를 통해 속성이나 메소드를 사용한다. 상속에서 사용하는 것과 같은 특별한 문법이 필요없다. 앞단의 클래스는 뒷단 클래스의 주요 기능을 확장하거나 새롭게 정의하는데 있어 자유롭다.
https://www.oops4u.com/163

 

 

반응형

'JavaScript > React' 카테고리의 다른 글

create-react-app  (0) 2021.03.08
리액트 시작하기-기본적으로 필요한 툴  (0) 2021.03.08
6. 이벤트 처리  (0) 2021.02.02
5.1 State 올바르게 사용하기  (0) 2021.02.01
5. State와 생명주기  (0) 2021.02.01