오늘은 받아들이는 영역입니다.
'암기'하세요. 그래야 훗날 '이해'가 됩니다.
객체지향적 프로그래밍은 '확장성'과 '유지보수'가 목표입니다.
'확장성'과 '유지보수'가 안된다면 그건 객체지향 프로그래밍이 아닙니다.
객체지향 프로그래밍(OOP : Object-Oriented Programming)은 현대 프로그래밍 패러다임 중 가장 주류가 된 프로그래밍 패러다임입니다.
절차지향 프로그래밍 언어에서는 어떤 타입을 설계할 때, 데이터만 정의할 수 있었습니다.


그리고 데이터를 프로그래머가 마음대로 외부에서 조작할 수 있는 것도 실수할 여지가 있었습니다.

그래서 객체지향 프로그래밍에서는 데이터와 데이터를 다루는 함수를 같이 작성할 수 있게 했으며, 이를 캡슐화(Encapsulation)라고 합니다.
또 객체를 올바르게 사용할 수 있도록 접근 한정자를 제공해 외부에 공개할 것과 그렇지 않은 것을 구분짓게 했습니다.
이를 데이터 은닉(Data Hiding)이라고 합니다.
객체지향 프로그래밍에서 데이터 부분을 필드, 함수를 메소드라고 합니다.
즉, 캡슐화란 데이터랑 함수를 같이 쓸 수 있게 만들어 준것입니다.
상속은 코드를 물려 받는 기능으로 코드를 재사용할 수 있게 합니다.
상속을 이용하면 더 작은 단위로 모듈화를 할 수 있습니다.

부모 클래스는 두 개가 될 수 없습니다.
즉, 단일 상속만 가능합니다.

자식 클래스에서는 부모 클래스의 private 멤버를 제외하고 접근할 수 있습니다.
하지만 필드는 자식에게도 공개하지 않는 것이 좋은 설계입니다.



많은 형태를 가지고 있다. 라는 한문 뜻입니다.
다형성은 객체지향에서 핵심입니다.
다형성은 같은 인터페이스로 서로 다른 동작을 하게 됩니다.
다형성은 객체지향의 핵심으로, 조건문을 암시적으로 만들어 프로그램을 확장할 때 큰 변화를 들이지 않아도 된다는 장점이 있습니다.
가령 캐릭터가 갖고 있는 직업군에 따라 줄 수 있는 물리 데미지가 다르다고 해보겠습니다.


자식 클래스 타입의 인스터스는 부모 클래스 타입의 변수에 저장할 수 있습니다.
이를 업캐스팅(Upcasting)이라고 합니다.
(암시적으로 진행됩니다.)

반대로 부모 클래스 타입에 담긴 자식 클래스 인스턴스를 다시 본래 타입으로 다룰 수도 있습니다. 이를 다운캐스팅(Downcasting)이라고 합니다.
(명시적으로 진행됩니다.)

업캐스팅과 다운캐스팅은 서로 상속 – 파생 관계가 아니라면 오류를 일으킬 수 있습니다.


// Magician을 Warrior타입으로 변환하고 있습니다.
// 런타임 에러이며, 프로그램이 터집니다.


문법 : < expression > as < type >
< expression > is < type > ? (< type >)(< expression >) : (< type >)null과 같다.
as 연산자를 사용하지 않았을 때

as 연산자를 사용하면?



// characers[1]은 Magician이다. Magician은 방어력을 따로 설정하지 않았기 때문에 null값으로 빈 공간이 출력된다.

// characers[0]은 Warrior이다. Warrior에 방어력을 13으로 설정했다.
가상 멤버를 이용하면 자식 클래스에서 재정의(Overriding)를 할 수 있어, 업캐스팅으로 인스턴스를 다룬다고 할 때, 멤버의 사용은 같지만 실제 타입에 따라 다른 동작을 만들어낼 수 있습니다.
가상 멤버는 다형성을 제공하기 위한 핵심 기능입니다.
가상 멤버 앞에 virtual 한정자를 붙이며, 가상 멤버가 될 수 있는 것은
메소드, 프로퍼티, 인덱서와 이벤트입니다. 즉, 함수인 것들만 가능합니다.
재정의를 하려면 가상 함수의 반환 타잎 앞에 overrride 한정자를 붙입니다.





올바른 상속을 확일할 수 있는 방법은 'is a' 방법입니다.
Circle is a Shapes => 문맥이 맞다.
Rectangle is a Shapes => 문맥이 맞다.
Triagle is a Shapes => 문맥이 맞다.
하지만 만약 관계 없는 단어를 사용했다고 가정한다면,
Plus is a Shpaes => 문맥이 맞지 않다. 즉, 코드 재사용성에만 목적을 둔 것이라고 판단할 수 있다.
좋지 못한 코드 입니다.
타입은 정말 중요합니다.
타입을 제대로 확인하고 코드를 작성해야합니다.

C++ 창시자 바야네 스트롭스트룹은 추상화에 대해 '구현 세부 정보를 숨기는 일반적인 인터페이스를 정의하는 행위'라고 정의했습니다.
인터페이스에 대한 정의가 생소할 수 있으니 이에 대해 먼저 알아보겠습니다.
인터페이스의 영영 사전 정의

해석하자면 서로 다른 부분이 만나고 소통하거나 서로에게 영향을 미치는 영역을 의미합니다.
실례를 들자면 선풍기를 조작한다고 할 때, 우리는 버튼을 눌러서 조작하게 되며, 선풍기가 내부적으로 어떻게 돌아가는지 잘 모릅니다. 이때 버튼을 인터페이스라고 할 수 있습니다.
정리하자면 추상화를 잘 하면 잘 할 수록 데이터를 다루기 쉬워지게 되며, 이는 프로그램을 더 빠르고 편리하고 안전하게 작성할 수 있다는 것을 의미합니다.
또한, 구현 세부 사항에 변화가 생기게 되더라도 사용하는 입장에서는 달라지는 것이 없으므로 확장성 또한 가지게 된다고 할 수 있습니다.
abstract 한정자를 이용하면 추상화 추상 클래스를 만들거나 추상 멤버를 만들 수 있습니다.
추상 클래스를 만들면 인스턴스를 만드는 것이 불가능해집니다.

// 추상 타입은 불완전하기 때문에 인스턴스를 만들 수 없습니다.
추상 멤버는 virtual 한정자와 마찬가지로 메소드, 인덱서, 이번트만 가능합니다.
다만, 가상 멤버와 다르게 추상 멤버는 재정의를 강제합니다.


높은 수준의 추상화를 위해 인터페이스를 사용할 수 있습니다.
인터페이스는 동작을 정의하는 용도로 사용하는 것이기 때문에 추상 클래스처럼 인스턴스를 만드는 것이 불가능하며, 모든 멤버가 추상 멤버입니다.

단, 인터페이스는 다중 상속할 수 있습니다.
인터페이스 안에 작성할 수 있는 멤버는 인스턴스 메소드, 프로퍼티, 인덱서, 이벤트와 정적 생성자, 필드, 상수, 연산자 입니다.


인터페이스 만들 때 규칙
이름 앞에 무조건 I를 붙여야합니다.
접근 한정자를 사용하지 않아도 됩니다.
인터페이스는 '구현했다.'라고 표현합니다.
