객체 지향 프로그래밍은 코드 내의 모든 것을 객체(Object)로 표현하고자 하는 프로그래밍 패러다임이다.
캡슐화
상속
다형성
추상화
내부 필드, 메소드, 프로퍼티 등 외부에서 어떻게 접근 가능한지 수식해주는 한정자.
객체간의 상호 작용이 중심인 OOP에선 각 객체는 다른 객체에게 자신의 내부 사정을 공유하지 않는다.
다른 객체에게 공유해야 하는 멤버만 접근한정자를 이용하여 공개한다.
접근한정자는 멤버(필드, 메소드 등등)를 외부에 어떤 수준으로 공개할지 지정한다.
부모 클래스에서 정의되고 자식 클래스에서 override 한정자를 이용하여 재정의할 수 있는 메서드로
가상 메서드는 미리 virtual로 한정
class Animal
{
public virtual void Init()
{
Console.WriteLine("초기화");
}
}
class Dog:Animal
{
public override void Init()
{
base.Init();
Console.WriteLine("Dog 초기화");
}
}
abstract 키워드를 사용하여 선언되며, 추상 메서드를 포함할 수 있다.객체지향 프로그래밍에서 "유지보수 잘 되는 코드"를 만들기 위한 다섯 가지 원칙의 약자.
객체지향에서 클래스를 어떻게 설계하고 책임을 분리하면 좋을지 알려주는 핵심 가이드라인이다.
클래스는 하나의 책임만 가져야 한다.
좋은 예시) Monster 클래스는
Attack(),Die()등 몬스터 기능만 담당
나쁜 예시) Monster 클래스에SaveData()등 저장까지 몬스터가 담당
클래스는 확장에 열려 있고, 변경에는 닫혀 있어야 한다.
다형성과 확장을 위해 추상화 사용을 권장하는 원칙
자식 클래스는 부모 클래스를 대체할 수 있어야 한다.
자식 타입 객체가 부모 타입의 객체에서 가능한 기능을 수행할 수 있어야 한다.
Bird라는 부모 클래스에 가상 메서드Fly()가 있다.
좋은 예시)Eagle : Bird-- Can Fly
나쁜 예시)Chick : Bird-- Can't Fly (LSP 위반)
이 경우에 Bird에서 Fly() 함수를 빼고 IFlyingBird 같은 인터페이스로 분리해야 한다.
인터페이스는 작게 나누어 클라이언트가 자신이 쓰지 않는 메서드에 의존하지 않게 해야 한다.
인터페이스는 작고 구체적으로 분리 해야한다.
인터페이스 단일 책임을 강조하는 것
좋은 예시)
interface IAnimal { void Sleep(); void Eat(); }
나쁜 예시)interface IAnimal { void Sleep(); void Fly(); }// 모든 동물이 날지 않는다.
구현이 아닌 추상(인터페이스)에 의존해야 한다.
클래스는 구체적인 클래스가 아니라, 코드의 결합도를 낮추기 위해 인터페이스나 추상 클래스에 의존해야 한다.
좋은 예시)
interface IWeapon { void Attack(); } class Gun : IWeapon { public void Attack() => Console.WriteLine("BAAANG!"); } class Sword : IWeapon { public void Attack() => Console.WriteLine("WHOOOSH!"); } class Player { private IWeapon weapon; public Player(IWeapon weapon) => this.weapon = weapon; public void Attack() => weapon.Attack(); }나쁜 예시)
class Gun { public void Shoot() => Console.WriteLine("Bang!"); } class Player { private Gun gun = new Gun(); public void Attack() => gun.Shoot(); ?}