- 객체들이 공통적으로 필요로 하는 속성이나 동작을 하나로 추출해내는 작업
- 추상화의 결과가 클래스이다.
과일
이라는 추상적인 개념에사과
,배
와 같은 구체화된 객체가 존재.- 클래스(
과일
)에 의존함으로써 어떤 객체(바나나
)가 추가되어도 보수에 큰 비용이 들지 않는다.
attribute와 method를 하나로 묶는다.
이때, 객체 내의 멤버변수에 직접적인 접근을 제한한다.
객체 본인의 멤버변수에 대한 접근은 본인만 가능하도록 함
이러한 제한은 객체 자체의 응집도를 높이고, 다른 객체들간의 의존도(결합도)를 낮춤
-> 유지 보수와 코드의 재사용성에 유리하다는 OOP의 철학에 더 가까워질 수 있다.
상속은 대상이 되는 클래스의 모든 특징(필드값, 메서드)들을 물려 받는 것
어떤 클래스를 이미 상속 받은 클래스를 다시 다른 클래스가 상속을 받을 수 있고, 이 과정이 반복되며 계층형 구조를 만들어 냄
ex) 생물 -> 동물 -> 포유류 -> 인간
구체화 <= 인간 - 포유류 - 동물 - 생물 => 일반화
상속을 하면 이미 구현된 세부 내용을 다시 구현할 필요가 없기 때문에 코드의 재사용성(resusability)이 향상되는 효과를 볼 수 있다.
상속관계는 두 클래스가
IS-A
[~은 ~이다] 관계인 경우와 기능의 확장을 통한 구체화하는 상황에서 권장된다. 무분별한 상속은 계층도의 결합력을 높여 유지관리의 이점이 사라질 수 있다.ex) 바나나는 과일이다
- has-a 관계인 클래스를 상속하지 않도록 주의하자
ex) 바나나는 껍질이 있다 X
하나의 속성이나 행위가 상황에 따라 다른 의미로 해석될 수 있는 특징이다.
상속과 오버라이딩을 통해 구현가능하다.
코드로 보는게 빠를 듯 하다
위와 같이 Fruit라는 클래스를 상속받은 Apple, Banana, Pear가 존재한다면
class Fruit { public void pill() {}; } class Apple extends Fruit { @Override public void pill() { System.out.println("Apple Way") }; } class Banana extends Fruit { @Override public void pill() { System.out.println("Banana Way") }; } class Pear extends Fruit { @Override public void pill() { System.out.println("Pear Way") }; }
아래와 같은 코드를 통해 다형성 구현을 맛볼 수 있다.
public class PlayGround { List<Fruit> fruits = new List<Fruit>(); fruits.add(new Apple()); fruits.add(new Banana()); fruits.add(new Pear()); foreach(Fruit fruit in fruits) { fruit.pill() } }
내가 구체적으로 어떤 클래스 객체(instance)에 의존하는지 관계없이, 각 객체들의
pill()
이 실행 되었다.
- 이렇게 다형성을 통한 유연한 설계는 변경에 대해 유연한 대처를 기대할 수 있다.