클래스는 객체를 만드는 틀이다.
클래스에는 객체가 가지고 있어야 하는 상태와 행위를 정의하고 있다.
객체는 클래스를 통해 생성될 소프트웨어내의 사람 혹은 사물이다.
인스턴스는 실제로 생성된 객체이다. 즉, 메모리에 할당되어 있는 상태이다.
즉, 객체는 선언되어 있는 상태이고, 인스턴스는 메모리에 할당된 상태이다.
인스턴스가 객체에 포함된다고 볼 수 있고 객체는 모든 인스턴스를 대표한다.
1) 코드의 재사용성
2) 유지보수 용이함
3) 대형 프로젝트에 적합
1) 처리 속도가 절차 지향 프로그래밍에 비해 느림
2) 객체가 많아지면 용량도 커짐
3) 설계 시 많은 시간과 노력이 필요
추상화는 사물에서 필수 속성이나 행동을 추출하는 것으로 추출한 필수 속성을 바탕으로 객체를 묘사하고 유사성을 표현한다.
세부 속성의 경우 객체마다 다르게 구현될 수 있도록 할 수 있다.
Java에서는 인터페이스, 추상클래스를 활용할 수 있다.
인터페이스란 간단하게 말해서 껍데기만 있는 클래스이다.
멤버 변수, 멤버 함수를 가질 수 없고, 추상 메소드와 상수만 가질 수 있다.
(Java8부터 default 키워드를 쓰면 함수의 body를 쓸 수 있다.)
그렇기 때문에 변수 앞에는 public static final이 생략되어 있고 상수 앞에는 public abstract이 생략되어 있다.
인터페이스는 구현을 강제하기 때문에 인터페이스를 구현하는 클래스는 추상 메소드를 모두 구현해주어야 한다.
다중 상속이 가능하며 객체를 생성할 수 없다.
추상 메소드를 하나 이상 가진 클래스이거나 하나도 없는 클래스(의도적으로 추상 클래스로 만들었을 수도 있다)이다.
인터페이스와는 다르게 멤버 함수와 멤버 변수를 가질 수 있다.
단일 상속이 가능하며 추상 클래스로는 객체를 생성할 수 없다.
하지만, 추상 클래스를 구현하는 자식 클래스를 참조해서 추상 클래스의 객체를 생성할 수 있다.
캡슐화는 목적에 맞는 변수와 메소드를 클래스에 알맞게 구성하는 것을 말한다.
다른 클래스가 중요한 변수나 메소드에 함부로 접근하고 의존하는 것을 막기 위함이다.
정보은닉은 캡슐화를 하는 가장 큰 목적으로 접근 제어자를 통해 데이터를 보호한다.
이렇게 보호된 변수는 getter나 setter와 같은 메소드를 통해서만 간접적으로 접근이 가능하다. (정보를 함부로 변경할 수 없게 된다.)
정보은닉은 “높은 응집도”와 “낮은 결합도”를 유지할 수 있도록 설계해서 요구사항을 변경할 때 유연하게 대처하기 위함이다.
만약 두 개의 클래스의 결합도가 높다면 한 클래스의 변경 발생 시 다른 클래스 역시 변경해야 할 가능성이 커지기 때문에 “정보은닉”은 매우 중요하다.
응집도(Cohesion): 클래스나 모듈 안의 요소들이 얼마나 밀접하게 관련되어 있는지
결합도(Coupling): 어떤 기능을 실행하는 데 다른 클래스나 모듈에 얼마나 의존적인지
상속은 기존 클래스를 바탕으로 새로운 클래스를 만들어서 기존 클래스에 있는 기능을 재활용하거나 새로운 기능을 정의할 수 있게 한다.
상위 클래스를 재활용할 수 있기 때문에 하위 클래스의 개발 속도가 빨라진다.
코드 중복을 줄일 수 있다.
편리한 유지보수, 다형성을 구현할 수 있다.
상위 클래스를 상속받은 하위 클래스가 많을 경우 상위 클래스를 쉬이 바꿀 수 없다.
코드 재사용 목적으로 사용할 경우 상속 관계가 성립하지 않을 수 있다.
또한, 비슷하지만 다른 기능이 많을 경우 각각의 기능을 모두 구현하기 위해 클래스를 많이 만들어야 할 수 있다.
해결책으로는 객체 조립을 사용함으로써 필드에서 다른 객체를 참조하는 방식으로 구현한다.
코드 재사용 목적으로 상속을 사용하는 것을 지양한다.
다형성은 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미한다.
이는 곧 형태는 같지만 다른 기능을 할 수 있음을 의미한다.
상속을 이용하면 기능을 확장하거나 변경하는 것을 가능하게 해준다.
따라서 다형성을 이용하면 코드의 재사용, 코드 길이 감소 등 유지보수가 용이하도록 도와준다.
다형성의 대표적인 방법으로는 오버로딩과 오버라이딩이 있다.
오버로딩은 이름이 같지만 형태가 다른 여러 메소드를 구현하는 것이다.
메소드의 이름은 무조건 같아야 하고, 매개변수의 타입이나 개수를 다르게 한다.
리턴 타입도 달라질 수 있는데 이 때는 무조건 매개변수가 달라져야 한다.
오버라이딩은 부모 클래스를 상속받은 하위 클래스가 부모 클래스의 메소드를 재정의하는 것을 의미한다.