참고 자료 : https://velog.io/@min9288/백엔드-기술-면접-질문자바
객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임 중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법입니다.
과거에 코드를 작성하면 절차적으로 이루어지는 절차 지향적인 언어와는 달리 구성요소들이 객체 안에 담겨있어 특정 객체만 동작하게 하거나 데이터를 처리하기 등 다양한 일을 할 수 있게 되었다.
- 장점▶코드 재사용이 용이남이 만든 클래스를 가져와서 이용할 수 있고 상속을 통해 확장해서 사용할 수 있다.▶유지보수가 쉬움절차 지향 프로그래밍에서는 코드를 수정해야할 때 일일이 찾아 수정해야하는 반면 객체 지향 프로그래밍에서는 수정해야 할 부분이 클래스 내부에 멤버 변수혹은 메서드로 존재하기 때문에 해당 부분만 수정하면 된다. ▶대형 프로젝트에 적합클래스 단위로 모듈화시켜서 개발할 수 있으므로 대형 프로젝트처럼 여러 명, 여러 회사에서 프로젝트를 개발할 때 업무 분담하기 쉽다.
- 단점▶처리 속도가 상대적으로 느림▶객체가 많으면 용량이 커질 수 있음▶설계시 많은 시간과 노력이 필요
객체지향 프로그래밍은 크게 캡슐화, 상속, 추상화, 다형성으로 나눌 수 있습니다.
캡슐화,
객체 지향 프로그래밍에서 기능과 특성의 모음을 "클래스"라는 "캡슐"에 분류해서 넣는것이 캡슐화라고 합니다.
객체가 외부에 노출하지 않아야할 정보 또는 기능을 접근제어자를 통해 적절히 제어 권한이 있는 객체에서만 접근하도록 할 수 있기에, 코드의 수정이 일어났을 때 책임이 있는 객체만 수정하면 되어 영향 범위를 예측할 수 있습니다. 그리고, 뿐만 아니라 관련된 기능과 특성을 한 곳에 모으고 분류하기 때문에 객체 재활용이 원활해졌습니다.
상속,
상속은 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것입니다.
추상화,
추상화는 "공통의" 속성이나 기능을 묶어서 이름을 붙여 클래스를 설계하는 것 입니다.
다형성,
하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것 입니다. 즉 오버라이딩(Overriding), 오버로딩(Overloading)이 가능하다는 것 입니다.
- 오버라이딩 : 상위 클래스가 가지고 있는 메소드를 상속 받을 때 자식 클래스에서 메소드를 재 정의하는것을 말합니다.
- 오버로딩 : 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출할 수 있게 하는 것 입니다.
객체지향 설계 5대 원칙은 SOLID라 하며, 각 원칙의 앞글자를 따왔습니다.
SRP 단일 책임 원칙 (single responsiblity principle)
"한 클래스는 하나의 책임만 가져야 하고 그 책임을 수행하는데 집중되어 있어야 한다"
여기에서 하나의 책임이라는 것은 모호한 의미를 가집니다. 책임은 상황에 따라서 클수도 있고 작을수도 있기 때문입니다. 설계가 잘 되었는지 확인할 수 있는 중요한 기준은 변경입니다. 변경이 있을때 파급 효과가 적으면(딱 하나의 클래스만 수정해도 된다면) 단일 책임 원칙을 잘 따른 것입니다.
OCP 개방-폐쇄 원칙 (Open/closed principle)
"소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다"
요구 사항의 변경이나 추가사항이 발생했을때 기존 구성요소는 변경이 일어나지 않아야 하며, 기존 구성요소를 쉽게 확장해서 재사용 할 수 있어야 한다는 뜻입니다.
확장을 하려면 당연히 기존의 코드를 바꿔야 하는거 아닌가? 라고 생각할 수 있지만 다형성을 활용해서 기존의 코드를 바꾸지않고 확장할 수 있습니다.
인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현하는 경우 클래스를 새로 만드는 것은 기존 코드를 변경한 것이 아닙니다.
LSP 리스코프 치환 원칙 (Liskov substitution principle)
"프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다"
다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것입니다. 인터페이스를 구현한 구현체를 믿고 사용하려면 이 원칙이 필요합니다.
자동차 인터페이스에 앞으로 가는 기능인 엑셀이 있습니다. 하지만 하위 클래스에서는 엑셀을 뒤로가게 하는 기능으로도 만들수 있습니다.(컴파일 오류는 발생하지 않음) 하지만 이 인터페이스 규약에서 엑셀은 앞으로 가는 기능이기 때문에 하위 클래스에서는 이 기능을 보장 해줘야 합니다.
ISP 인터페이스 분리 원칙 (Interface segregation principle)
"특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다"
큰 덩어리의 인터페이스를 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 합니다. 인터페이스를 분리하게 되면 기능이 명확해지고, 대체 가능성이 높아집니다.
DIP 의존관계 역전 원칙 (Dependency inversion principle)
"프로그래머는 "추상화에 의존해야지, 구체화에 의존하면 안된다." 의존성 주입(DI)는 이 원칙을 따르는 방법 중 하나다"
쉽게 말하면 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 뜻입니다.
인터페이스에 의존하게 되면 구현 클래스에 대해서는 몰라도 되기 때문에 유연하게 구현체를 변경할 수 있습니다. 반대로 구현 클래스에 의존하게 되면 변경이 어려워 집니다.