본문 바로가기

JavaScript

자바스크립트 클래스의 고급 기능

728x90

자바스크립트 클래스의 고급 기능

 

private 속성과 메소드

 

📌 private 속성

클래스 내부에서만 접근 가능한 속성

사용자가 의도하지 않은 방향으로 사용하는 것을 막아 클래스의 안정성을 확보하기 위해 나온 문법

 

length속성을 음수로 변경하는 것을 막기 위해 만들어졌습니다.

    <script>
        // 정사각형을 나타내는 객체
        class Square {
            constructor(length){
                if(length < 0)
                    throw '길이는 0 이상이어야 합니다.'
                this.length = length
            }

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

        const square = new Square(10)
        console.log(square.getArea())
        console.log(square.getPerimeter())

        square.length = -10
        console.log(square.getArea())
        console.log(square.getPerimeter())
    </script>

 

📌  private 속성 사용하기

    <script>
        class Square {
            #length

            constructor(length){
                if(length < 0)
                    throw '길이는 0 이상이어야 합니다.'
                this.#length = length
            }

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

        const square = new Square(10)
        square.#length = -10
        console.log(square.getArea())
        console.log(square.getPerimeter())
    </script>

이렇게 만든 private 속성은 클래스 외부에서는 접근할 수 없으므로 사용자가 클래스를 잘못 사용라는 문제를 줄일 수 있습니다.

 

📌  게터(getter)와 세터(setter) 메소드

하지만, 현재 square 객체의 length속성이 몇인지 확인할 수 없고, length 속성을 변경하고 싶어도 변경할 수 없습니다. 그래서 개발자들은 상황에 따라서 속성을 읽고 쓸 수 있는 메소드를 만들어서 제공합니다.

    <script>
        class Square {
            #length

            constructor(length){
                this.length = length
            }

            set length (length) {
                if(length <= 0) {
                    throw '길이는 0보다 커야 합니다.'
                }
                this.#length = length
            }

            get length() {
                return this.#length
            }

            get Area() {
                return this.#length * this.#length
            }
            get Perimeter() {
                return this.#length * 4
            }
        }

        const square = new Square(10)
        console.log(`한 변의 길이는 ${square.length}입니다.`)
        console.log(`넓이는 ${square.Area}입니다.`)
        console.log(`둘레는 ${square.Perimeter}입니다.`)
        
        const squareA = new Square(-10)
    </script>


📌  만들어진 클래스 객체의 객수를 알고 싶을 때

 

    <script>
        // 만들어진 Square 객체의 개수를 알고 싶을 때
        let count = 0
        class Square {
            constructor(length) {
                count += 1
            }
        }

        console.log(count)
        new Square()
        new Square()
        new Square()
        console.log(count)
    </script>

위에 코드를 아래와 같이 변경할 수 있습니다.

 

클래스 이름.속성
클래스 이름.메소드()

조금 생소할 수 있으나 자바스크립트에서는 클래스 이름 뒤에 점을 찍고 속성과 메소드를 사용할 수 있습니다.

    <script>
        // 만들어진 Square 객체의 개수를 알고 싶을 때
        class Square {
            constructor(length) {
                Square.count += 1
            }
        }
        
        Square.count = 0
        Square.test = function (){

        }

        console.log(Square.count)
        new Square()
        new Square()
        new Square()
        console.log(Square.count)
    </script>

 

📌  static 속성과 메소드

비교적 최근에 추가된 문법으로 클래스안에 이와 같은 디자인 패턴을 활용하기 위해 사용합니다.

    <script>
        // 만들어진 Square 객체의 개수를 알고 싶을 때
        class Square {
            #a
            #test () {
                console.log('private test() 메서드입니다')
            }

            constructor() {
                this.#test()
            }
        }

        new Square() 
    </script>


상속(inheritance)

 

사각형과 정사각형의 둘레와 넓이를 구하는 클래스 작성

    <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{
            constructor (length) {
                this.length = length
            }

            getPerimeter() {
                return 4 * this.length
            }

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

        const rectangle = new Rectangle(10, 20)
        console.log(`사각형의 둘레 : ${rectangle.getPerimeter()}`)
        console.log(`사각형의 넓이 : ${rectangle.getArea()}`)

        const square = new Square(10)
        console.log(`정사각형의 둘레 : ${square.getPerimeter()}`)
        console.log(`정사각형의 넓이 : ${square.getArea()}`)
    </script>

코드를 살펴보면, 둘 다 사각형으므로 둘레와 넓이를 구하는 메소드가 비슷합니다.

클래스를 분리하는 것이 클래스를 활용하는 쪽에서는 편리하지만, 분리하면 클래스 선언 부분이 복잡해지는 문제가 발생합니다. 이러한 문제를 해결하기 위해 나온 것이 상속입니다.

 

class 클래스 이름 extends 부모 클래스 이름 {

}

상속은 말 그대로 부모 클래스(parent class)가 가지고 있는 유산(속성과 메소드)를 다른 클래스(child class)에게 물려주는 형태로 사용합니다.

 

    <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 rectangle = new Rectangle(10, 20)
        console.log(`사각형의 둘레 : ${rectangle.getPerimeter()}`)
        console.log(`사각형의 넓이 : ${rectangle.getArea()}`)

        const square = new Square(20)
        console.log(`정사각형의 둘레 : ${square.getPerimeter()}`)
        console.log(`정사각형의 넓이 : ${square.getArea()}`)
    </script>

 

📌  상속 예시

    <script>
        class Parent {
            test() {
                console.log('Parent.test() 메소드')
            }
        }

        class ChildA extends Parent {
            test() {
                super.test()
                console.log('ChildA.test() 메소드')
            }
        }

        class ChildB extends Parent {
            test() {
                console.log('ChildB.test() 메소드')
                super.test()
            }
        }

        new ChildA().test()
        new ChildB().test()
    </script>


오버라이드(override)

부모가 갖고 있는 메소드와 같은 이름으로 메소드를 선언해서 덮어 쓰는 것

    <script>
        class LifeCycle {
            call () {
                this.a()
                this.b()
                this.c()
            }

            a() { console.log('a() 메소드를 호출합니다.') }
            b() { console.log('b() 메소드를 호출합니다.') }
            c() { console.log('c() 메소드를 호출합니다.') }
        }

        class Child extends LifeCycle {
            a() {
                console.log('자식의 a() 메소드를 호출합니다.')
            }
        }

        new Child().call()
    </script>


참고한 책 : 혼자 공부하는 자바스크립트