개요
- 현대 프로그래밍 중 가장 주류가 된 프로그래밍
- 이름에서 알 수 있듯 객체지향 프로그래밍은 객체를 중심으로 프로그램을 구성하는 방법
캡슐화
- 객체지향 프로그래밍에서는 데이터와 데이터를 다루는 함수를 같이 작성할 수 있게 했고, 이를 캡슐화라고 함
- 객체를 올바르게 사용할 수 있도록 접근 한정자를 제공해 외부에 공개할 것과 그렇지 않은 것을 구분지을 수 있게 했는데, 이를 데이터 은닉이라고 함
- 객체지향 프로그래밍에서 데이터 부분을 필드(Field), 함수를 메소드(Method)라고 함
상속
- 코드를 물려 받는 기능으로 코드를 재사용할 수 있게 했고, 더 작은 단위로 모듈화 할 수 있음
- class Derived : Base에서 Base를 기저클래스 혹은 부모클래스라고 하고, 상속 받은 클래스를 파생클래스 혹은 자식클래스라고 함
- 부모 클래스는 두 개가 될 수 없음. 즉, 단일 상속만 가능
- 자식 클래스에서는 부모 클래스의 private 멤버를 제외하고 접근할 수 있음
- 하지만 필드는 자식에게도 공개하지 않는 것이 좋은 설계
- 보통의 경우는 private, protected, public 만 주로 사용함
생성 순서
- 자식 클래스 객체를 생성할 경우 생성 순서는 부모 -> 자식 순서
- 호출 순서도 부모-자식 순서이지만, 소멸 순서는 역순으로 자식 -> 부모 순서
sealed 클래스
- 상속을 막고 싶은 경우 sealed 한정자를 사용
다형성
- 같은 인터페이스로 서로 다른 동작을 하게 함
- 객체지향의 핵심으로, 조건문을 암시적으로 만들어 프로그램을 확장할 때 큰 변화를 들이지 않아도 된다는 장점이 있음
- 다형성을 이용하면 조건문이 사라짐
업캐스팅과 다운캐스팅
- 자식 클래스 타입의 인스턴스는 부모 클래스 타입의 변수에 저장할 수 있음 (암시적)
- 업캐스팅이라고 함

- 반대로 부모 클래스 타입에 담긴 자식 클래스 인스턴스를 다시 본래 타입으로 다룰 수도 있음 (명시적)
- 다운캐스팅이라고 함

- 업캐스팅과 다운캐스팅은 서로 상속-파생 관계가 아니라면 오류를 일으킬 수 있음
- 이러한 타입변환을 안전하게 하고 싶다면 is 연산자와 as 연산자를 사용할 수 있음

- is의 예시. is 연산자는 bool 타입

- as의 예시 (캐스팅을 할 수 있을 때)

- as의 예시 (캐스팅을 할 수 없을 때 null을 반환)
가상 멤버
- 가상 멤버를 이용하면 자식 클래스에서 재정의를 할 수 있어, 업캐스팅으로 인스턴스를 다룬다고 할 때, 멤버의 사용은 같지만 실제 타입에 따라 다른 동작을 만들어낼 수 있음
- 다형성을 제공하기 위한 핵심 기능
- 멤버 앞에 virtual 한정자를 붙이며, 가상 멤버가 될 수 있는 것은 메소드, 프로퍼티, 인데것와 이벤트. 즉, 함수인 것들만 가능
sealed 멤버
- 클래스에 sealed를 붙이면 더 이상 상속할 수 없던 것처럼, 가상 멤버에 sealed를 붙여 재정의를 하면 더 이상 재정의를 할 수 없게 됨
추상화
- 추상 : 추상이 붙는 경우 불완전하다고 생각
- 구현 세부 정보를 숨기는 일반적인 인터페이스를 정의하는 행위
- Interface : 서로 다른 부분이 만나고 소통하거나 서로에게 영향을 미치는 영역을 의미
- 예시를 들자면 선풍기를 조작한다고 할 때, 버튼을 눌러서 조작하게 되며, 내부적인 작동원리는 잘 모름. 이때 버튼을 인터페이스라고 볼 수 있음
- 추상화를 잘하면 잘할수록 데이터를 다루기 쉬워지게 되며, 이는 프로그램을 더 빠르고 편리하고 안전하게 작성할 수 있음을 의미
- 구현 세부 사항에 변화가 생기더라도 사용하는 입장에서는 달라지는 것이 없으므로 확장성 또한 가지게 됨
추상 클래스와 추상 멤버
- abstract 한정자를 이용하면 추상 클래스나 추상 멤버를 만들 수 있음
- 추상 클래스를 만들면 인스턴스를 만드는 것이 불가능해짐
- 추상 멤버는 virtual 한정자와 마찬가지로 메소드, 프로퍼티, 인덱서, 이벤트만 가능
- 가상 멤버와는 다르게 추상 멤버는 재정의를 강제함

- 추상 멤버의 예시. 위 예시의 Shape는 더 이상 인스턴스를 만들 수 없음 (추상 클래스로 만들었기 때문)
인터페이스
- 높은 수준의 추상화를 위해 인터페이스를 사용할 수 있음
- 동작을 정의하는 용도로 사용하는 것이기 때문에 추상 클래스처럼 인스턴스를 만드는 것이 불가능하며, 모든 멤버가 추상 멤버
- 다중 상속할 수 있음
- 인터페이스 안에 작성할 수 있는 멤버는 인스턴스 메소드, 프로퍼티, 인덱서, 이벤트와 정적 생성자, 필드, 상수, 연산자

- 클래스는 “상속했다”라고 표현하고, 인터페이스는 “구현했다”라고 표현하는 것이 일반적