ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ES6의 Class, extends, super
    thoughts 2019. 7. 29. 15:45

    1. Class?

     

    클래스란 비슷한 object들을 쉽고 빠르게 만들 수 있도록 도와주는 도구다. ES6 문법이 업데이트되며, 자바스크립트에 Class라는 새로운 키워드가 도입되었다.

     

    각각의 학생의 정보를 담고 있는 object를 만든다고 가정해 보자. 우리의 작업을 도와주는 클래스 키워드가 없다면, object를 하나 하나 직접 만들어야 한다.

    let student1 = {
      name: 'Bob the turtle',
      age: 80,
      hobby: 'swimming'
      sayHello: function(){
        return `Hello ${name}`
      },
      goodAt: function(){
        return `${name} is VERY good at ${hobby}`
      }
    }
    
    let student2 = {
      name: 'Tom the cat',
      age: 3,
      hobby: 'sleeping',
      sayHello: function(){
        return `Hello ${name}`
      },
      goodAt: function(){
        return `${name} is VERY good at ${hobby}`
      }
    }
    
    let student3 = {
      name: 'peter the rabbit',
      age: 10,
      hobby: 'hopping',
      sayHello: function(){
        return `Hello ${name}`
      },
      goodAt: function(){
        return `${name} is VERY good at ${hobby}`
      }
    }
    
    // and so on...

    학생의 수가 적다면 object들에 정보를 입력하는 일이 그다지 어렵지 않을 수도 있겠다. 그러나 위와 같은 방법-객체 리터럴 방식-을 사용하여 훨씬 많은 학생의 정보를 입력해야 한다면? 시간도 오래 걸릴 뿐더러, 각 학생이 중복으로 갖는 메소드 sayHello, goodAt에 대해서 각각 메모리가 할당되기 때문에 상당히 비효율적이다. 상기한 문제를 해결하는 데에 클래스가 해답이 될 수 있다.

     

    class Student {
      constructor(name, age){
        this.name = name;
        this.age = age;
      }
      function sayHello(){
        return `Hello ${name}`
      }
      function goodAt(){
        return `${name} is VERY good at ${hobby}`
      }
    }
    
    let student1 = new Student('Bob the turtle', 80);
    let student2 = new Student('Tom the cat', 3);
    let student1 = new Student('Peter the rabbit', 12);
    
    console.log(student1.sayHello()) // 'Hello Bob the turtle'
    console.log(student1.age) // 80
    

    'Bob the turtle'의 정보가 담긴 인스턴스를 살펴보며, Class 키워드를 통해 인스턴스를 만들어내는 방법을 좀 더 구체적으로 뜯어보자.

    첫째로, Student 클래스를 통해 새로 만들어질 인스턴스를 담을 변수 'student1'을 선언했다. 

    두 번째로, new 키워드를 사용해 Student 클래스의 새로운 인스턴스를 생성했다. new 키워드는 클래스 안의 constuctor 메소드를 호출한다. 즉, constructor()는 class에서 새로운 인스턴스를 찍어낼 때마다 호출이 되며, 만들어낸 새로운 인스턴스를 리턴한다.

    세 번째로, Student의 constructor에 'Bob the turtle'과 80이라는 값을 넣었다.

    console.log를 통해 student1 인스턴스가 잘 만들어졌는지 확인해 보자. student1.sayHello()를 호출하면 메소드 sayHello가 올바른 값을 리턴한다는 사실을 확인할 수 있다.

     

    클래스를 이용하면, 객체 리터럴 방식을 이용할 때보다 훨씬 간편하게 학생들의 정보를 담고 있는 인스턴스를 만들어 낼 수 있다. 

     

     

    2. Psudoclassical instantiation vs ES6's class

     

    ES6 업데이트로 class가 도입되기 전, 자바스크립트에서는 class를 흉내내어 인스턴스를 만들어 내는 방법이 네 가지(Functional, Functional shared, prototypal, psudoclassical) 있었다. 그 가운데 psudoclassical 방식과 ES6의 Class 방식을 비교해 보도록 하겠다.

     

    먼저 psudoclassical instantiation으로 클래스와 인스턴스를 만들어 보겠다.

    Function Cat(name, age){
    // 프로퍼티
      this.name = name;
      this.age = age; 
    }  
    
    // 메소드
    Cat.prototype.sayMeow = function(){
      return 'MEOW.. Obey me human!'
    } 
    
    Cat.prototype.howOld = function(){
        return 'I am ' + age + ' years old.'
    }
    
    var oden = new Cat('oden', 10);
    
    console.log(oden) // {name: 'oden', age: 10};
    console.log(oden.sayMeow) // 'MEOW.. Obey me human!'

    Psudoclassical에서는 생성자 함수 Cat을 통해 프로퍼티의 값을 받는다는 점을 확인할 수 있다. 메소드는 프로토타입으로 만들어 주면 된다.

     

    ES6의 class 키워드를 사용해서, 같은 형태의 인스턴스를 만들어 보자.

    Class Cat{
      constructor(name, age){ // 프로퍼티
        this.name = name;
        this.age = age; 
      } 
      //메소드
      sayMeow() {
        return 'MEOW.. Obey me human!'
      }
      howOld(){
        return `I am ${age} years old.`
      }
    }
    
    
    var oden = new Cat('oden', 10);
    
    console.log(oden) // {name: 'oden', age: 10};
    console.log(oden.sayMeow) // 'MEOW.. Obey me human!'

    psudoclassical과 달리, constructor()를 호출하여 프로퍼티를 설정한다는 사실을 확인할 수 있다. 메소드 설정 또한 다른 방식으로 이루어지는데, Cat 클래스 안에 메소드를 열거하면 된다. 이 때 주의할 부분은 메소드 사이에 콤마를 쓰면 안 된다는 점이다.

     

    3. Inheritance -  extends, super

     

    상속이란 상위 객체의 특징을 하위 객체에게 넘겨주는 것을 의미한다. 상속을 통해, 자식 객체는 부모 객체의 기능을 물려받으면서도 동시에 또 다른 기능을 가질 수 있다. ES6에서는 extends와 super 키워드를 통해 상속이 가능하다. 예제를 통해 살펴보자.

    Class Pet{
      constructor(name, age){
        this.name = name;
        this.age = age;
      }
      howOld(){
       return `I am ${age} years old.`
      }
    }

    Pet이라는 클래스를 만들었다. 이 클래스에는 반려동물이라면 공유하는 특징(이름 프로퍼티, 나이 프로퍼티, 몇 살인지 알려주는 메소드)이 설정되어 있다. Pet을 부모 클래스로 하는, 자식 클래스들을 만들어보자. 먼저 Cat 클래스를 만들었다.

    class Cat extends Pet{
      constructor(name, age){
        super(name, age);
      }
      sayMeow(){
        return 'MEOW! Obey me human!'
      }
    }

    extends 키워드를 사용한 덕에, Pet 클래스의 메소드를 Cat 클래스 내부에서 사용할 수 있었다. constructor는 두 가지 argument, 즉 name과 age를 받았다. 이 두 argument는 super(name, age)가 이어 받는다. super 키워드는 받은 argument들을 Pet 클래스의 constructor에 전달하는 역할을 한다. 따라서 Cat의 constructor 내부에 별도로 name, age 프로퍼티를 설정하는 부분이 없더라도, Cat클래스를 통해 만들어진 인스턴스는 name, age 프로퍼티를 가지게 된다.

    constructor 아래에 있는 sayMeow 메소드는 고양이만의 특별한 메소드다. 따라서 Pet 클래스가 아니라 Cat 클래스에 설정되었다. 당연하게도, Pet 클래스만을 이용해 만들어진 인스턴스에서는 sayMeow를 호출할 수 없다. 

    이어서 Dog 클래스를 만들었다.

    class Dog extends Pet{
      constructor(name, age, lovesWalking){
        super(name, age);
        this.lovesWalking = lovesWalking;
      }
    }

    constructor가 받는 세 가지 argument가운데 lovesWalking을 주목해 보자. 강아지가 산책을 좋아하는지 아닌지에 대한 정보를 담는 프로퍼티로서, boolean을 값으로 한다. '산책'은 강아지만의 속성이므로(가끔 산책냥이가 있다는 사실은.. 여기서는 살짝 잊도록 하자) Dog 클래스만의 고유한 프로퍼티로 설정해 주었다. 다시 말해 Pet 클래스의 constructor에 lovesWalking은 전달해 줄 필요가 없으므로, super 키워드에 lovesWalking argument를 넣지 않았다. 이처럼, 부모 클래스를 상속하여 만들어진 자식 클래스는 해당 클래스만의 고유한 프로퍼티/메소드를 가질 수 있다.  

     

     

     

    댓글

Designed by Tistory.