2022 스터디/영어 스터디[2022]

[4] What is object-oriented programming? OOP explained in depth

EYR 2022. 5. 15. 15:13

본 글은

https://www.educative.io/blog/object-oriented-programming

 

What is object-oriented programming? OOP explained in depth

Learn what is OOP, the building blocks of an OOP program, the four principles that make up OOP, and more.

www.educative.io

요 사이트의 번역입니다.

문제가 되면 내립니다.

 

볼드체나 이미지, 코드등도 원본 글을 따릅니다.

이미지는 원본 글에서 링크로 참조합니다.

 

Attributes -> 속성

Behaviors -> 동작

으로 통일합니다.

 

What is object-oriented programming? OOP explained in depth

객체 지향 프로그래밍은 무엇인가? OOP에 대한 자세한 설명

 


 객체 지향 프로그래밍(Object-oriented programming ,OOP)은 거의 대부분의 개발자가 제각각의 곳에 사용하는 근본적인 프로그래밍 방식이다. OOP는 가장 대중적인 프로그래밍 방식이며 이는 프로그래머 교육생이 코드를 짜는 기본적인 방식이다.

 

  이 글에서는 무엇이 프로그램을 객체 지향적으로 만드는지에 대한 기본을 분석하여 프로젝트와 작업에 이 양식을 활용할 수 있도록 할 것이다.

 

다루는 내용들:

  • 무엇이 객체 지향 프로그래밍인가?
  • OOP를 구성하는 요소들
  • OOP의 4 원칙
  • 다음에 배울 내용

 

What is Object Oriented Programming? 무엇이 객체 지향 프로그래밍인가?

  객체 지향 프로그래밍(OOP)는 클래스객체(objects)라는 개념에 따른 프로그래밍 방식이다. 이는 소프트웨어 프로그램을 간단하고 재사용될 수 있는 객체의 개별 인스턴스를 만드는 코드의 설계도(클래스라고 불리는)를 구조화하기 위해 사용된다. JavaScript, C++, Java, Python 과 같은 많은 객체 지향 프로그래밍 언어들이 존재한다.

 

  클래스(class)는 더 특정적이고 개념적인 객체를 만들기 위한 추상적인 청사진이다. 클래스들은 특징을 공유하는 CarDog 같은 광범위한 부분을 대표하기도 한다. 이러한 클래스들은 이 타입이 어떤 속성의 인스턴스를 가질지를 정의한다. 마치 color 같이 말이다. 그러나 특정 객체에 대한 속성 값은 아니다.

 

  클래스들은 또한 해당 유형의 객체에만 사용 가능한 메소드(methods)라고 불리는 함수를 포함한다. 이 함수들은 클래스 내에서 정의되었고 특정 유형의 객체를 돕는 행동을 수행한다.

 

예를 들면, Car 클래스는 차의 color 속성을 바꾸는 repaint라는 메소드를 가질 수 있다. 이 함수는 Car 타입의 객체에게만 적용될 수 있다. 그렇기 때문에 Car 클래스 내에서 메소드를 정의한다.

  클래스 템플릿은 특정한 객체를 만들기 위한 청사진으로 쓰인다. 이는 myCar goldenRetriever같은 추상 클래스의 구체적인 예시를 뜻한다. 각각의 객체는 클래스에 정의된 프로퍼티(properties)에서 특징적인 값을 가질 수 있다.

예를 들면, 차가 가져야 할 프로퍼티인 color, brand, model를 포함하는 Car라는 클래스를 만들었다면, 특징적인 나만의 차를 대표하기 위해 myCar라는 Car타입의 인스턴트 객체를 만들 수 있다.

그런 뒤, my car에 따라 정의된 클래스의 프로퍼티의 값을 클래스 템플릿의 다른 객체에 영향을 미치지 않고 설정할 수 있다.

그럼 이 클래스를 재사용해 원하는 수의 차를 나타낼 수 있다.

 

 

두개의 Car 타입 객체, myCar과 helensCar를 만드는데 사용되는 클래스 청사진.

 

 

Benefits of OOP OOP의 장점

  • OOP는 복잡한 것들을 사용 가능하고 간단한 형식으로 구조화해준다.
  • 재사용가능한 OOP 객체들은 프로그램들을 넘어 사용될 수 있다.
  • 다형성에 따른 클래스별 행동을 가능하게 한다.
  • 디버그 하기 더 쉽다. 클래스는 적용할 수 있는 모든 정보를 포함하기도 한다.
  • 보안적이다. 캡슐화를 통한 정보 보호가 가능하다.

 

 

How to structure OOP programs OOP 프로그램을 구성하는 방법

  실제 문제를 마주하고, 개념적으로 OOP 소프트웨어 프로그램을 디자인 해 보자.

 

  수백마리의 반려견들을 돌보는 애견 호텔(원문: dog sitting camp)을 운영한다고 생각해보자. 그들의 이름, 나이, 그리고 각각 맡겨질 일수를 기억하고 정리해야 한다(keep track). 어떻게 개들을 위한 간단하고 재사용 가능한 소프트웨어 모델을 디자인 할 것인가?

 

  수백마리의 개들이라면 각각에 대한 특정한 코드를 짜는건 어려울 것이다. 아래의 코드에서 예시로 두 객체 rufus와 fluffy를 볼 수 있다.

//첫 번째 개에 대한 객체
var rufus = {
    name: "Rufus",
    birthday: "2/1/2017",
    age: function() {
        return Date.now() - this.birthday;
    },
    attendance: 0
}

//두 번째 개에 대한 객체
var fluffy = {
    name: "Fluffy",
    birthday: "1/12/2019",
    age: function() {
        return Date.now() - this.birthday;
    },
    attendance: 0
}

  위에서 볼 수 있듯이 두 객체의 코드 사이에는 여러 복제 코드(같은 코드)들이 존재한다. age() 함수는 각각의 객체에 모두 나타난다. 우리가 각각의 개들에게 같은 정보를 원하기 떄문에, 우리는 객체와 클래스를 대신 사용할 수 있다.

 

  클래스 구조화를 위해 정보에 따라 한데로 묶는 그룹핑(grouping)은 코드를 짧고 쉽게 유지할 수 있도록 한다.

  애견 호텔 예시에서 프로그래머가 OOP로 조직화할 수 있는 방법은 다음과 같다:

  1. 모든 개들에 대한 상위 클래스(parent class)를 만든다. 타입과 상관없이 모든 개들이 가진 정보와 행동(메소드)을 청사진으로 구성한다.
  2. 하위 클래스(child classes)를 만들어 개들의 각기 다른 하위 카테고리를 나타낸다. 상위 클래스의 청사진을 따른다.
  3. 고유한 속성과 행동을 추가한다. 이는 하위 클래스의 다름을 표현할 수 있다.
  4. 하위 클래스로부터 객체를 생성한다. 하위 그룹에 속하는 개들을 표현할 수 있다.

 

  아래의 도표는 OOP 프로그래밍을 어떻게 설계하는지 알려준다:

  하나의 템플릿을 만들기 위해 주어진 데이터와 동작을 하나로 그룹핑하고 고유한 데이터와 동작을 위해 하위그룹을 만든다.

 

  Dog 클래스는 일반 템플릿이다. 모든 개들에게 일반적으로 해당되는 데이터와 동작만을 구조로 포함하고 있다.

 

  그리고 Dog 아래에 두 개의 하위 클래스 HerdingDogTrackingDog을 만든다. 이들은 상속받은 동작 Dog(bark())을 가지고 있지만 또한 하위그룹에서의 고유한 개들의 동작 또한 가진다.

 

  마침내, 고유한 개 FluffyMaisel을 나타내기 위해 HerdingDog타입의 객체를 만든다.

 

  우리는 또한 Dog의 광범위한 클래스 객체들에는 알맞지만 HerdingDog나 TrackingDog에는 알맞지 않은 Rufus 라는 객체를 만들 수 있다.

 

 

Building blocks of OOP OOP를 구성하는 요소들

  그다음으로, 다음에 따른 OOP 프로그램 각각의 근본적인 구성 요소를 살펴볼 것이다:

  • 클래스(Classes)
  • 객체(Objects)
  • 메소드(Methods)
  • 속성(Attributes)

 

Classes 클래스

  쉽게 말해서, 근본적으로 클래스는 유저가 정의한 데이터 타입이다.

  클래스는 메소드와 속성의 구조를 집어넣어 만드는 청사진이다. 고유한 객체들은 인스턴스화 되거나 이 청사진으로부터 만들어진다.

 

  클래스는 속성과 동작에 따른 메소드 영역을 포함한다. Dog 클래스를 예로 들자면, 속성은 name & birthday를 포함한다. 메소드는 bark()updateAttendance()를 포함한다.

 

  아래의 코드에는 JavaScript 언어에서 Dog 클래스는 프로그래밍 하는 과정이 단편적으로 나타나 있다.

class Dog {
    constructor(name, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    //Declare private variables
    _attendance = 0;

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return Date.now() - this.birthday;
    }
    
    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

  클래스는 dog을 모델링하기 위한 템플릿이라는 것을 기억하라. 그리고 객체는 클래스 내에서 인스턴스화 되어 실제 세계의 개별적인 사물을 나타낸다.

Enjoying the article? Scroll down to sign up for our free, bi-monthly newsletter.
*광고글이지만... 원문을 존중해서 함께 실어 둡니다... ^,^...

 

 

Objects 객체

  OOP는 당연히 객체를 포함한다. 객체들은 특정한 데이터와 함께 생성된 클래스의 인스턴스이다. 예시로 나와있는 아래에 코드에서 RufusDog 클래스의 인스턴스이다.

class Dog {
    constructor(name, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    //Declare private variables
    _attendance = 0;

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return Date.now() - this.birthday;
    }
    
    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

//instantiate a new object of the Dog class, and individual dog named Rufus
const rufus = new Dog("Rufus", "2/1/2017");

클래스 Dog가 새로 호출되었을 때:

  • 새 객체는 만들어져 rufus라 이름지어진다.
  • 생성자가 name & birthday 인수를 실행하고 값을 할당한다.
프로그래밍 어휘:
JavaScript의 객체는 변수의 한 타입이다. 아래에 나와있는 것 처럼 JavaScript의 객체는 클래스 템플릿 없이 선언될 수 있어 혼란을 일으킬 수 있다.

객체들은 상태와 동작을 가지고 있다. 상태는 데이터로 정의될 수 있다:
개에 지정하고 싶은 이름이나, 생일, 혹은 다른 정보가 포함될 수 있다. 동작은 객체가 가질 수 있는 메소드이다.
N/A 활용 담고 있는 정보 행위(Action) 예시
클래스 청사진 특성 메소드로 정의된 행동 Dog 템플릿
객체 인스턴스 상태, 데이터 메소드 Rufus, Fluffy

 

 

Attributes 속성

  속성은 저장된 정보이다. 속성은 Class 템플릿 안에 정의되었다. 객체가 인스턴트화 되면 고유적인 객체는 속성 영역에 저장된 데이터를 포함한다.

 

  객체에 대한 상태는 객체의 속성 안의 데이터에 의해 정의된다. 예를 들면 강아지와 개는 애견 호텔에서 다르게 돌보아야 할 수도 있다. 생일은 객체의 상태에 대해 정의될 수 있고 소프트웨어는 개들의 나이에 따라 그들을 다르게 다룰 수 있다.

 

 

Methods 메소드

  메소드는 행동을 정의한다. 메소드는 행위를 이행한다; 메소드는 객체나 업데이트 된 객체의 데이터에 대한정보를 리턴할 수 있다. 메소드의 코드는 클래스 정의에 의해 정의된다.

 

  고유 객체가 인스턴트화 되면, 이 객체들은 클래스에 정의된 모든 메소드를 호출할 수 있다. 아래에 명시된 코드에서 Dog 클래스에 정의된 bark 메소드가 Rufus 객체에 의해 호출된다.

class Dog {
    //Declare protected (private) fields
    _attendance = 0;

    constructor(name, birthday) {
        this.namee = name;
        this.birthday = birthday;
    }

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }

    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

  메소드는 데이터를 수정하거나 업데이트, 삭제하기도 한다. 하지만 이는 필수적이지 않다. 예를 들면 bark() 메소드는 아무 데이터를 업데이트하지 않는다. 왜냐면 barkingDog 클래스에 있는 name이나 birthday 중 어느 속성도 수정하지 않기 때문이다.

 

  updateAttendance() 메소드는 Dog가 애완 호텔에 묵는 날을 추가한다. 출석(attendance) 특성은

워월 말에 주인들에게 대한 요금을 계산하는 데에 필수적이다. (원문: The attendance attribute is important to keep track of for billing Owners at the end of the month.)

 

  메소드는 프로그래머가 재사용을 촉진하고 객체 내부에 캡슐화된 기능을 유지하는 방법이다. 이 재사용성은 디버깅을 진행할때 큰 이점이 된다. 만약 에러가 있다면, 단지 한 곳만 수정하면 된다.

 

  _attendance의 밑줄은 변수가 보호되어있고 직접적으로 변경되어서는 안된다는 것을 나타낸다. updateAttendance() 메소드는 _attendance를 변경하기 위해 사용된다.

 

Keep the learning going.
Learn OOP without scrubbing through videos or documentation. Educative’s text-based courses are easy to skim and feature live coding environments - making learning quick and efficient.

Learn OOP in JavaJSPython, C++C#
*광고광고

 

 

 

 

 

 

 

Four Principles of OOP OOP의 4 원칙

  객체 기반 프로그래밍의 네 가지 기반은 다음과 같다:

  • 상속(Inheritance): 하위 클래스는 상위 클래스로부터 데이터와 동작을 상속받는다.
  • 캡슐화(Encapsulation): 객체 안에 정보를 포함시킴으로서 오직 선택된 정보만 노출시킨다.
  • 추상화(Abstraction): 객체에 접근하기 위한 높은 수준의 공개 메소드에만 노출시킨다.
  • 다형성(Polymorphism): 많은 메소드들이 같은 작업을 수행할 수 있다.

 

Inheritance 상속

  상속은 클래스들이 다른 클래스에 특징을 물려줄 수 있게 해준다. 다른 말로 하자면, 상위 클래스는 하위 클래스로 속성과 동작을 확장할 수 있다. 상속은 재사용성을 지원한다.

 

  만약 기본적인 속성과 동작이 상위 클래스에 정의되어 있다면, 하위 클래스는 상위 클래스의 기능을 확장하여 생성될 수 있다. 또한 추가로 속성과 동작을 추가할 수 있다.

 

  예를 들면, 목축견들는 동물을 모는 고유한 능력을 가지고 있다. 다시 말해서, 모든 목축견들은 개들이다. 하지만 모든 개들이 목축견은 아니다. 우리는 이 다름을 상위 클래스 Dog로부터 하위 클래스 HerdingDog를 만듬으로서 표현한다. 그리고 herd()라는 동작을 추가한다.

 

  상속의 필요성은 프로그램은 일반적인 상위 클래스를 만들고 더욱 특징적인 하위 클래스를 원하는 만큼 만들 수 있음에 있다. Dog라는 클래스 구조를 여러번 만드는 것 대신 전반적인 프로그래밍에 대한 단순화는 하위 클래스가 자동적으로 상위 클래스 내의 기능에 접근할 수 있도록 한다.

 

 아래의 코드에서 하위 클래스 HerdingDog 는 부모 클래스 Dog로부터 메소드 bark를 상속받는다. 그리고 하위 클래스는 별개의 herd()라는 메소드를 추가한다.

//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;

    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }

    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

//Child class HerdingDog, inherits from parent Dog
class HerdingDog extends Dog {
    constructor(name, birthday) {
        super(name);
        super(birthday);
    }

    herd() {
        //additional method for HerdingDog child class
        return console.log("Stay together!")
    }
}

  HeringDog 클래스는 bark()라는 메소드의 복사본을 가지지 않고, 상위 클래스인 Dog에서 정의된 bark()를 상속함에 주의하라. 

 

  코드가 fluffy.bark() 메소드를 호출하면 bark() 메소드는 정의된 bark 메소드를 찾기 위해 하위 클래스에서 상위 클래스로 이어진 체인을 따라 이동한다.

//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;

    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }

    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

//Child class HerdingDog, inherits from parent Dog
class HerdingDog extends Dog {
    constructor(name, birthday) {
        super(name);
        super(birthday);
    }

    herd() {
        //additional method for HerdingDog child class
        return console.log("Stay together!")
    }
}

//instantiate a new HerdingDog object
const fluffy = new HerdingDog("Fluffy", "1/12/2019");
fluffy.bark();
참조: Parent class(부모 클래스는) super class(상위 클래스) 혹은 base class로도 불린다.
Child class(자식 클래스)는 derived class(파생 클래스) 또는 extended class(확장 클래스)라고도 한다.

*본 번역에선 상위 클래스/하위 클래스 로 통일했습니다.

  JavaScript에서 상속은 프로토타입(prototyping)으로도 불린다. 프로토타입 객체는 속성과 동작을 상속받기 위한 다른 객체의 템플릿처럼 작동한다. 다수의 프로토타입과 객체 템플릿이 존재할 수 있고 프로토타입 체인을 생성할 수 있다.

 

  이것은 상위/하위 상속과 같은 개념이다. 상속은 상위에서 하위로 향한 것이다. 예시에서 3마리의 개들은 모두 bark할 수 있지만 Maisel Fluffy만이 herd할 수 있다.

 

  herd() 메소드는 HerdingDog 하위 클래스에 정의되었기에 이로부터 인스턴스화 된 두 객체, Maisel Fluffyherd() 메소드에 접근할 수 있다. Rufus는 상위 클래스 Dog로부터 인스턴스화된 객체이다. 그렇기 때문에 Rufus bark() 메소드에만 접근할 수 있다.

 

객체 클래스로부터의 인스턴스화 상위 클래스 메소드
Rufus Dog N/A bark()
Maisel Herding Dog Dog bark(), herd()
Fluffy Herding Dog Dog bark(), herd()

 

 

Encapsulation 캡슐화

  캡슐화는 객체 안에 모든 중요한 정보를 포함한다는 걸 의미한다. 그리고 오직 선택된 정보만이 바깥에 노출된다. 속성과 동작은 클래스 템플릿 안에 정의되어 있다.

 

  그러므로 객체가 클래스로부터 인스턴트화 되면 데이터와 메소드는 그 객체 안에 캡슐화된다. 캡슐화는 클래스 내에 구현되어있는 소프트웨어 내부의 코드와 객체 내부의 데이터를 숨긴다.

 

  캡슐화는 영역이 공개적인지 비공개적인지에 대한 정의를 요구한다.

  • 비공개/내부 인터페이스(Private/ Internal interface): 메소드와 프로퍼티는 같은 클래스의 다른 메소드에서만 접근 가능하다.
  • 공개/외부 인터페이스(Public / External Interface): 메소드와 프로퍼티는 클래스 바깥에서도 접근 가능하다.

  캡슐화의 비유로 차를 들어보자. 차가 회전을 표시하기 위해 깜박이를 사용하여 외부와 공유하는 정보는 공개 인터페이스이다. 반면에, 엔진은 보닛(원문: hood) 아래에 숨겨져 있다.

 

  이는 비공개적이고 내부 인터페이스이다. 도로를 따라 차를 몰고 있으면, 다른 운전자들은 결정을 위한 정보를 요구한다. 좌회전이나 우회전 깜빡이 같은. 그러나, 엔진 온도와 같은 내부의 비공개된 데이터를 노출하는 건 다른 운전자들을 혼란스럽게 할 뿐이다.

 

 

  캡슐화는 보안성을 더한다. 속성과 메소드는 비공개적으로 설정될 수 있고 클래스 바깥에서 접근할 수 없게 된다. 객체 안의 데이터에 대한 정보를 얻어 접근하거나 데이터를 업데이트 하기 위해선 공개 메소드 & 프로퍼티가 사용되어야만 한다.

 

이는 개발자가 클래스 정의에서 공개 방법을 통해 객체에 어떤 데이터를 노출시킬 수 있는지를 선택하는 보안 계층을 추가하게 해 준다.

 

  대부분의 프로그래밍 언어는 클래스에 공개, 보호, 비공개 섹션을 가지고 있다. 공개는 메소드를 바깥이나 프로그램 내부의 다른 클래스에서도 사용하게끔 해주는 제한된 섹션이다.

  비공개 코드는 오직 클래스 내에서만 접근될 수 있다. 개/오너 예시로 돌아가보자면 캡슐화는 오너들로 하여금 다른 사람의 개에 대한 비공개 정보를 열람할 수 없게 하기 때문에 이상적이다.

참조: JavaScript는 프로퍼티와 메소드를 비공개적이거나 보호받게 설정할 수 있다. 보호받은 영역들은 _ 가 앞에 붙여준다. 비공개적인 영역들은 #를 앞에 붙여준다. 보도받은 영역들은 상속 가능하지만 비공개적인 것들은 불가능하다.
//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;

    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }

    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

//instantiate a new instance of Dog class, an individual dog named Rufus
const rufus = new Dog("Rufus", "2/1/2017");
//use getter method to calculate Rufus' age
rufus.getAge();

  예시 코드의 getAge() 메소드를 생각해 보면, 계산과정은 Dog 클래스 안에 숨겨져 있다. rufus 객체는 Rufus의 나이를 계산하기 위해 getAge() 메소드를 사용한다.

  캡슐화 & 데이터 업데이트: 메소드가 객체의 데이터 또한 수정 가능하기 때문에, 개발자는 공개 메소드를 통해 어떤 값이 바뀔 수 있는지에 대해 통제한다.

 

  이는 중요한 정보를 숨길 수 있게 만들어준다. 피싱이나 더 가능성 있는 시나리오인 다른 개발자의 실수로 중요한 데이터를 수정하는 것을 막아준다.

 

  캡슐화는 코드에 보안성을 추가하고 외부 개발자와 더 협력하기(collaborate) 쉽게 만든다. 외부 회사와 정보를 공유하기 위해 프로그래밍을 할 때, 클래스의 템플릿이나 비공개적인 데이터를 노출시키고 싶진 않을 것이다. 왜냐면 그 지적 재산권은 내부 회사에 있기 때문이다.

 

  대신, 개발자들은 다른 개발자가 객체에 메소드를 호출할 수 있게 공개 메소드를 만든다. 이 공개 메소드는 외부 개발자들을 위해 이상적으로 작업을 할 수 있게 해준다.

 

  캡슐화의 필요에 대한 요약은 다음과 같다:

  • 보안성을 추가한다: 공개된 메소드와 특성만이 바깥에서 접근 가능하다.
  • 일반적인 실수로부터 보호한다: 오직 공개된 필드와 메소드만이 접근 가능하다. 그래서 개발자들은 실수로 위험한 것을 바꾸지 않을 것이다.
  • IP를 보호한다: 코드는 클래스 안에 숨겨져 있기 때문에 오직 공개적인 메소드만이 바깥 개발자들이 접근 가능하다.
  • 지원 안정성: 대부분의 코드는 업데이트 및 개선을 거친다.
  • 복잡하게 숨긴다: 아무도 오브젝트의 커튼 뒷면을 볼 수 없다!

 

Abstraction 추상화

  추상화는 유저가 오직 선택된 객체에 특성과 메소드에만 상호작용함을 뜻한다. 추상화는 단순화, 고레벨도구(high level tools)로 복잡한 객체에 접근한다.

  • 복잡함을 나타내기 위해 단순한 것들을 사용한다
  • 유저에게 복잡한 디테일들을 숨긴다.

  추상화는 단순한 클래스복잡성을 나타내기 위해 사용된다.

  추상화는 캡슐화의 확장이다. 예를 들면, 차를 몰기 위해 엔진이 어떻게 작동하는지에 대해선 알 필요가 없다.

 

  운전자는 악셀, 브레이크, 운전대, 깜빡이 같은 작은 섹션의 도구만을 사용한다. 내부 구조는 드라이버로부터 숨겨져 있다. 차를 작동시키려면 보닛 아래에서 많은 부품들이 작동해야만 한다. 그러나 그 정보를 운전자에게 확장시키는 건 혼란을 초래할 수 있다.

 

 

  추상화는 또한 중요한 보안 규칙을 제공한다. 오직 선택된 데이터의 조각만을 표시함으로서, 그리고 오직 데이터를 클래스와 메소드를 통한 수정으로만 접근 허용함으로서 데이터를 노출로부터 보호할 수 있다. 차 예시를 계속하자면 운전하면서 가스 탱크가 열리는 건 아무도 원하지 않을 것이다.

 

  추상화의 필요성에 대한 요약은 다음과 같다:

  • 단순하고 고차원의 유저 인터페이스를 제공한다
  • 복잡한 코드는 숨겨진다
  • 보안성
  • 소프트웨어 유지가 더 쉬워진다
  • 코드는 추상화를 거의 변경하지 않는다.

 

Polymorphism 다형성

  다형성은 객체들이 동작을 공유하도록 설계되었음을 뜻한다. 상속을 사용함으로서 객체는 쉽게 상위 동작으로부터 특정한 하위 동작으로 공유할 수 있다. 다형성은 동일한 메소드를 메소드 오버라이딩과 메소드 오버로딩(method overriding and method overloading)의 두가지 방식으로 사용할 수 있게 한다:

 

Method Overriding 메소드 오버라이딩

  런타임 다양성은 메소드 오버라이딩을 사용한다. 메소드 오버라이딩에서 하위 클래스는 상위 클래스와는 다른 구현을 해낼 수 있다. 개 예시에서 TrackingDog에 일단 개들과 다른 특별한 타입의 bark를 준다고 해보자.

메소드 오버라이딩은 상위 Dog 클래스의 메소드를 오버라이딩(덮어쓰는)하는 bark() 메소드를 하위 클래스에 만들 수 있다.
//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;

    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }

    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

//Child class TrackingDog, inherits from parent
class TrackingDog extends Dog {
    constructor(name, birthday)
        super(name);
        super(birthday);
    }

    track() {
        //additional method for TrackingDog child class
        return console.log("Searching...")
    }

    bark() {
        return console.log("Found it!");
    }


//instantiate a new TrackingDog object
const duke = new TrackingDog("Duke", "1/12/2019");
duke.bark(); //returns "Found it!"

 

TrackingDog가 bark() 메소드를 오버라이딩 하는 모습

 

 

 

Method Overloading 메소드 오버로딩

  컴파일 시간 다형성은 메소드 오버로딩을 사용한다. 함수의 메소드들은 같은 이름을 가지고 있을 수 있다. 하디만 다른 숫자의 메개변수가 메소드 호출에 사용된다. 다른 메개변수에 들어오는 숫자에 따라 다른 결과가 나타날 수 있다.

//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;

    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    getAge() {
        //Getter
        return this.calcAge();
    }

    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }

    bark() {
        return console.log("Woof!");
    }

    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }

    updateAttendance(x) {
        //adds multiple to the dog's attendance days at the petsitters
        this._attendance = this._attendance + x;
    }
}

//instantiate a new instance of Dog class, an individual dog named Rufus
const rufus = new Dog("Rufus", "2/1/2017");
rufus.updateAttendance(); //attendance = 1
rufus.updateAttendance(4); // attendance = 5

  예를 들어 이 코드에선, 만약 updateAttendance() 메소드에는 아무 메개변수도 걸리지 않는다. 카운트에 하루가 추가되었다. 만약 메개변수가 updaterAttendance(4)를 지나가면 updaterAttendance(x)x변수에는 4가 걸리게 된다. 그리고 카운트에 4 일이 추가된다.

 

다형성의 필요성은 다음과 같다:

  • 다른 유형의 객체들이 동일한 인터페이스를 통해 전달될 수 있다.
  • 메소드 오버라이딩
  • 메소드 오버로딩

 

Conclusion 결론

  객체 지향 프로그래밍은 코드의 처음부터 프로그램의 구조에 대한 생각을 요구한다. 객체를 인스턴스화 시키기 위해 팔요한 청사진을 만들기 위해 요구사항을 어떻게 쉽고, 재사용 가능한 클래스들로 만드는지 살펴보았다. 전반적으로 OOP는 더 나은 구조와 재사용성을 만들어준다. 러닝 타임 또한 줄여준다.

 

 

If you’d like to take a deep dive into OOP, Educative has courses for OOP in:

These courses are text-based with in-browser coding environments so you can learn even faster and more efficiently. No set-up required, just get in and start coding.

Happy learning!

 

Continue reading about Object Oriented Programming