본문 바로가기
JavaScript

JavaScript_Class

by Testengineer 2022. 8. 28.
반응형

객체 지향 프로그래밍 언어들은 클래스라는 문법으로 객체를 효율적으로 만들어 쉽게 프로그래밍에 적용할 수 있게 한다. 

프로그램에 필요한 요소만 사용해서 객체를 표현하는 것을 추상화라고 한다. 

보통 클래스와 프로토타입이라는 문법으로 객체를 효율적으로 만든다. 클래스는 객체를 만들 때 수많은 지원을 하는 대신 많은 제한을 걸고 프로토타입은 제한이 많이 없지만, 지원도 별로 없다.

클래스를 기반으로 만든 객체는 인스턴스라고 부른다. 그냥 객체라고 부르는 경우도 있다. 붕어빵 틀이 클래스라면, 만들어진 붕어빵은 인스턴스라고 볼 수 있다.

BreadTool이라는 클래스를 만들고 Breads라는 객체를 리스트로 만들어 각 내용을 push()를 사용해 추가했다. 이렇게 하면 빵 종류별로 총판매금액을 계산할 수 있다. 그리고 constructor 생성자를 사용했다. 사용할 때는 클래스 이름으로 호출해서 사용한다. 메소드로는 getTotal()과 toString()을 추가했다. 내부적으로 메소드가 중복되지 않고 하나만 생성되어 활용된다.

<!DOCTYPE html>

<head>
    <title></title>
    <script>

        class BreadTool{
            constructor (name, ingredient, count ,price){
                this.name = name
                this.ingredient = ingredient
                this.count = count
                this.price = price
            }


        getTotal () {
            return this.count* this.price
        }

        toString() {
            return `${this.name}\t${this.getTotal()}\n`
        }

       
    }

        const Bread = new BreadTool()

        const Breads = []
        Breads.push(new BreadTool('corn bread','corn',10,3000))
        Breads.push(new BreadTool('cake','whipped cream',2,30000))
        Breads.push(new BreadTool('donut','chocolate',7,2500))
        Breads.push(new BreadTool('baguette','flour',5,4000))


        let output = '이름\t총 판매금액\n'
        for (const i of Breads) {
            output += i.toString()
        }

        console.log(output)
    </script>
</head>
<body>
    
</body>
</html>

 

상속(Inheritance)

클래스를 분리해서 사용하는 것이 클래스 활용에서는 편리하나 선언 부분이 복잡해질 수 있다. 그럴 때 상속을 사용한다. 상속은 클래스의 선언 코드를 중복해서 작성하지 않음으로써 코드의 생산 효율성을 높이는 방법이다.

상속은 속성과 메소드를 다른 클래스에게 물려주는 형태로 사용한다. 이때 전해주는 클래스를 부모 클래스, 받는 클래스를 자식 클래스라고 한다.

<!DOCTYPE html>

<head>
    <title></title>
    <script>
        class Rectangle{
            constructor(width, height){
                this.width = width
                this.height = height
            }

            getPerimeter(){
                return 2*(this.width+this.height)
            }

            getArea(){
                return this.width*this.height
            }
        }

        class Square extends Rectangle{
            constructor(length){
                super(length, length)
            }

        }


        const square = new Square(10,20)
        console.log(`둘레: ${square.getPerimeter()}`)
        console.log(`넓이: ${square.getArea()}`)
    </script>
</head>
<body>
    
</body>
</html>

여기서 Rectangle이라는 클래스가 부모 클래스이고 Square클래스는 속성과 메소드를 상속받아 사용했다. 

 

private 속성과 메소드

클래스 사용자가 클래스의 속성 또는 메소드를 의도치 않은 방향으로 사용하는 것을 막기 위해 private를 사용한다. 속성과 메소드 앞에 #을 붙인다. private를 사용하려면 사용하기 전에 미리 외부에 어떤 속성을 private 하겠다고 미리 선언해야 한다.

<!DOCTYPE html>

<head>
    <title></title>
    <script>
        class Square{
            #length

            constructor(length){
                this.setLength(length)
            }

            setLength(value){
                if(value<=0){
                    throw '0보다 커야 한다'
                }
                this.#length = value
            }

            getLength(value){
                return this.#length
            }

            getPerimeter(){
                return this.#length*4
            }

            getArea(){
                return this.#length*this.#length
            }
        }

        const square = new Square(10)
        console.log(`둘레는 ${square.getPerimeter()}이다`)
        console.log(`한변의 길이는 ${square.getLength()}이다`)

    </script>
</head>
<body>
    
</body>
</html>

private 속성을 사용하면 클래스 외부에서는 해당 속성에 접근할 수 없다. 속성 값을 변경하면 변경되지 않는다. 그래서 #length 속성에 접근하기 위해서 getter와 setter를 사용한다. 위의 코드에서는 getLength()와 setLength() 메소드를 추가했다. get메소드처럼 속성 값을 확인할때 사용하는 메소드를 getter라고 하며, 속성에 값을 지정하는 것을 setter라고 한다.

 

static 속성과 메소드

static 속성과 메소드는 인스턴스를 만들지 않고 사용할 수 있는 기능이다. 클래스 이름 뒤에 점을 찍고 속성과 메소드를 사용한다.

<!DOCTYPE html>

<head>
    <title></title>
    <script>
         class Square{
            #length
            static #counter = 0
            static get counter(){
                return Square.#counter
            }

            constructor(length){
                this.length = length
                Square.#counter += 1
            }

            static perimeterOf(length){
                return 4*length
            }

            static areaOf(length){
                return length*length
            }

            setLength(value){
                if(value<=0){
                    throw '0보다 커야 한다'
                }
                this.#length = value
            }

            getLength(value){
                return this.#length
            }

            getPerimeter(){
                return this.#length*4
            }

            getArea(){
                return this.#length*this.#length
            }
        }

        const squareA = new Square(10)
        const squareB = new Square(20)

        console.log(`생성된 인스턴스는 ${Square.counter}개 이다`)
        console.log(`한변의 길이가 20인 정사각형 둘레는 ${Square.perimeterOf(20)}이다.`)
        console.log(`한변의 길이가 10인 정사각형 넓이는 ${Square.areaOf(10)}이다.`)

    </script>
</head>
<body>
    
</body>
</html>

#counter라는 static 속성과 counter()라는 static 메소드를 생성했다. #counter 속성을 이용해 객체의 생성자가 호출될 때마다 1씩 증가해 총객체가 몇 개 생성되었는지 확인할 수 있다. 

 

오버라이드(Override)

부모가 갖고 있는 함수를 자식에서 다시 선언해서 덮어쓰는 것을 오버라이드라고 한다. 자식에서 새로 선언하면 새로운 메소드 내용이 사용된다. 만약 부모에 있던 메소드의 내용을 사용하고자 한다면 super.메소드()  형태를 사용하면 부모에 있던 메소드도 사용 가능하다.

앞에서 작성했던 코드 중에 toString() 메소드가 있는데 이것이 오버라이드이다. 사실 toString()메소드는 모든 객체에서 갖고 있다. 자바스크립트가 Object라는 최상위 클래스를 가지고 있어서 어떤 클래스를 만들어도 자동으로 Object 클래스를 상속받기 때문이다.

반응형

'JavaScript' 카테고리의 다른 글

JavaScript_예외처리  (0) 2022.08.30
JavaScript_객체  (0) 2022.08.25
JavaScript_함수  (0) 2022.08.21
JavaScript_반복문  (0) 2022.08.14
JavaScript_기본 자료형 & 조건문  (0) 2022.08.07

댓글