- 클래스 : 분류, 집합 같은 속성과 기능을 가진 객체를 총칭하는 개념.
- 객체 : 세상에 존재하는 유일무이한 사물
객체와 클래스를 구분하는 간단한 방법은 나이(혹은 제조년일)를 물어보는 것.
- 사람의 나이는? 답할 수 없으므로 클래스
- 김연아의 나이는? 답할 수 있으므로 객체
- 펭수의 나이는? 답할 수 있으므로 객체
- 펭귄의 나이는? 답할 수 없으므로 클래스
- 접근 제어자인 private, [default], protected, public, 그리고 접근자 및 설정자 메서드 등을 통해 객체의 상태를 보호한다.
- 상속을 받지 않았다면 객체 멤버는 객체를 생성한 후 객체 참조 변수를 이용해 접근해야 한다.
- 정적 멤버는 클래스명.정적멤버 형식으로 접근하는 것을 권장한다. 이는 일관된 형식으로 접근하기 위해서 사용되어진다. 객체를 생성한 경우에는 객체참조변수명.정적멤버 형태로도 접근할 수 있다.
- Call By Reference, Call By Value의 차이는 기본 자료형 변수는 저장하고 있는 값을 그 값 자체로 해석하는 반면, 객체 참조 변수는 저장하고 있는 값을 주소로 해석한다는 차이가 있을 뿐이다.
2.상속(extends ; 확장) : 재사용
- 재사용과 확장으로 이해하는 것이 맞다. (동물의 분류도와 같은 예)
- 객체지향에서의 상속은 상위 클래스의 특성을 하위 클래스에서 상속(특성 상속)하고 거기에 더해 필요한 특성을 추가, 즉 확장해서 사용할 수 있다는 의미인 것이다.
- 상위 분류 - 하위 분류, 그리고 상위 클래스 쪽으로 갈수록 추상화, 일반화 되었다고 하며, 하위 클래스로 갈수록 구체화, 특수화 되었다고 말한다.
- "하위클래스는 상위클래스이다" 라는 문장은 로버트 C. 마틴이 주장하고 모두가 동의하는 객체지향 설계 5원칙 가운데 LSP(리스코프 치환 원칙)을 나타내는 말이다.
- 자바에서 사용하는 상속의 키워드는 extends. "확장"이다.
- 하위 클래스 is a 상위 클래스 보다는 하위 클래스 is a kind of 상위 클래스( 하위클래스는 상위클래스의 한 분류이다. )가 더 명확한 영어 표현이다.
- 인터페이스는 구현 클래스 is able to 인터페이스(구현클래스는 인터페이스할 수 있다). ex) 고래는 헤엄칠 수 있다.
- 인터페이스는 "무엇을 할수 있는" 이라는 표현 형태로 만드는 것이 좋다.
- 자바 API 에서도 이러한 be able to 형식의 인터페이스가 있다.
(1) Serializable 인터페이스 : 직렬화할 수 있는
(2) Cloneable 인터페이스 : 복제할 수 있는
(3) Comparable 인터페이스 : 비교할 수 있는
(4) Runnable 인터페이스 : 실행할 수 있는
- 상위클래스는 하위 클래스에게 물려줄 특성이 많을 수록 좋고(LSP:리스코프 치환 원칙), 인터페이스는 구현을 강제할 메서드가 적을수록 좋다.(ISP:인터페이스 분할 원칙)
- 하위 클래스의 인스턴스가 생성될 때 상위 클래스의 인스턴스도 함께 힙영역에 생성된다.( 최상위 클래스인 Object 클래스의 인스턴스도 함께 생성된다는 것 )
class Animal {
public String name;
public void showName() {
System.out.printf("안녕 나는 %s야. 반가워\n", name );
}
}
class Penguin extends Animal {
public String habitat;
public void showHabitat() {
System.out.printf("%s는 %s에 살아\n", name, habitat );
}
}
public class Driver {
public static void main(String[] args) {
Penguin pororo = new Penguin();
pororo.name = "뽀로로";
pororo.habitat = "남극";
pororo.showName();
pororo.showHabitat();
Animal pingu = new Penguin();
pingu.name = "핑구";
// pingu.habitat = "EBS";
pingu.showName();
// pingu.showHabitat(0;
// Penguin happyfeet = new Animal();
}
}
출력결과
java Driver
안녕 나는 뽀로로야. 반가워
뽀로로는 남극에 살아
안녕 나는 핑구야. 반가워
위 소스를 예로 들면 소스가 아래와 같이 해석했을 때 논리적으로 이해하기 쉬운 코드가 되어야한다.
Penguin pororo = new Penguin();
// 펭귄 한 마리가 태어나니 펭귄 역할을 하는 pororo라 이름 지었다.
pororo.name = "뽀로로";
// pororo의 name을 "뽀로로"라 하자
pororo.habitat = "남극";
// pororo의 서식지를 "남극"이라 하자
pororo.showName();
// pororo야 너의 이름을 보여줘
pororo.showHabitat();
// pororo야 너의 서식지를 보여줘
위 처럼 잘 번역되어 읽히지 않으면 객체지향언어를 충분히 활용하지 못하고 있는 것이다.
3.추상화(Abstraction) : 모델링
- 추상화란 구체적인 것을 분해해서 관심 영역(애플리케이션 경계, Application Boundary)에 있는 특성만 가지고 재조합 하는 것 = 모델링
- 클래스를 설계하기 위해서는 애플리케이션 경계부터 정해야한다.
- 객체지향에서 추상화의 결과는 클래스이다.
클래스 객체참조변수 = new 클래스(); // 새로운 객체를 하나 생성해 그 객체의 주소값(포인터)을 객체 참조 변수에 할당
클래스 멤버 = static 멤버 = 정적 멤버 // 스태틱 영역
객체 멤버 = 인스턴스 멤버 // 힙 영역
로컬 변수 // 스택 영역(스택 프레임 내부)
정적 메서드는 객체들의 존재 여부에 관계없이 쓸 수 있는 메서드이다.
정적 멤버들은 객체가 아닌 클래스에 속해 있으며, 클래스는 JVM 구동시 스태틱 영역에 바로 배치되기 때문에 객체의 존재 여부에 관계없이 쓸 수 있다.
일단 main 메서드는 당연히 정적 메서드여야 한다. 주로 클래스의 인스턴스를 만들지 않고 사용하게 되는 유틸리티성 메서드들이 정적 메서드로 구성된다.
4.다형성(Polymorphism) : 사용 편의
- 객체지향에서 다형성이라고 하면 가장 기본은 오버라이딩(Overriding)과 오버로딩(Overloading)이라고 할 수 있다.
(1) 오버라이딩 : 같은 메서드 이름, 같은 인자 목록으로 상위 클래스의 메서드를 재정의
(2) 오버로딩 : 같은 메서드 이름, 다른 인자 목록으로 다수의 메서드를 중복 정의
- 상위 클래스 타입의 객체 참조 변수를 사용하더라도 하위 클래스에서 오버라이딩(재정의)한 메서드가 호출된다.