목표
자바의 상속에 대해 학습하세요.
학습할 것 (필수)
- 자바 상속의 특징
- super 키워드
- 메소드 오버라이딩
- 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
- 추상 클래스
- final 키워드
- Object 클래스
자바 상속의 특징
상속이란??
부모 클래스의 변수와 메소드를 물려받는 것을 의미한다.
- 조상 클래스 = 부모 클래스 = 상위 클래스 = 기반 클래스
- 자손 클래스 = 자식 클래스 = 하위 클래스 = 파생 클래스
❗ 주의 : 상속을 해도 부모 클래스의 모든 필드와 메소드를 물려받는 것은 아니다. 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속의 대상에서 제외되며 부모와 자식이 다른 패키지에서 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
특징
1. 자식은 extends 키워드를 통해 부모를 선택한다.
2. 자바에서는 다중 상속을 허용하지 않는다.
3. Object 클래스는 모든 클래스의 부모 클래스이다.
4. 상속 횟수에 제한이 없으며, final키워드가 붙은 클래스는 상속을 할 수 없다.
- final메소드 또한 오버라이딩이 불가능하다.
하위 클래스가 생성되는 과정
하위 클래스가 생성될 때 상위 클래스가 먼저 생성된다.
상위 클래스의 생성자가 호출되고 하위 클래스의 생성자가 호출된다.
하위 클래스의 생성자에서는 무조건 상위 클래스의 생성자가 호출되어야 함
하위 클래스에서 상위 클래스의 생성자를 호출하는 코드가 없는 경우 컴파일러는 상위 클래스 기본 생성자를 호출하기 위한 super()를 추가한다.
super()로 호출되는 생성자는 상위 클래스의 기본 생성자이다.
만약 상위 클래스의 기본 생성자가 없는 경우( 매개변수가 있는 생성자만 존재하는 경우) 하위 클래스는 명시적으로 상위 클래스의 생성자를 호출해야 함
상속에서의 메모리 상태
상위 클래스의 인스턴스가 먼저 생성되고
하위 클래스의 인스턴스가 생성된다.
상위 클래스로의 묵시적 형 변환
상위 클래스 타입 = 하위 클래스 타입 이런 식으로 형 변환이 가능하다.
하위 클래스 타입은 상위클래스 타입을 포함하고 있기때문에 상위클래스 타입은 하위클래스 타입으로 생성 가능하다 라고 이해하면 된다.
super 키워드
1. super()는 부모의 기본 생성자를 호출한다.
자식 클래스의 생성자에서 명시적으로 부모 생성자를 호출하고 싶으면 아래와 같은 구조로 작성하면 된다.
자식클래스 (매개변수) {
super(매개값);
}
2. super키워드는 부모 메소드를 호출할 때도 사용한다.
super.부모 메소드();
public class WhiteShip extends Floating {
private static final int NORMAL = 1;
private static final int HARD = 2;
public int FloatingMode = NORMAL;
@Override
public void floating() {
if (FloatingMode == HARD) {
System.out.println("WhiteShip이 떠다닌다.");
} else {
super.floating(); // 부모 메소드 호출
}
}
}
메소드 오버라이딩
메소드 오버라이딩이란?
메소드 오버라이딩이란(=메소드 재정의) 상속을 받은 자식 클래스에서 동일한 메소드의 내용을 재정의 하여,
이름은 같은 메소드이지만 전혀 다른 내용을 구현하는 기법(?)을 말한다.
메소드 오버라이딩 시 규칙
1. 부모의 메소드와 동일한 시그니처를 가진다.
2. 접근 제한을 강하게 하면 오버라이딩을 할 수 없으며, final 키워드가 붙은 메소드도 오버라이딩 할 수 없다.
3. 새로운 예외(Exception)를 throws 할 수 없다.
4. 재정의 할 때는 메소드 라인 위쪽에 @Override이라는 어노테이션을 붙인다. (생략해도 상관은 없으나, 컴파일러가 체크 + 다른 사람들이 알아보기 좋다.)
시그니처
1. 리턴 타입
2. 메소드 이름
3. 매개 변수의 타입과 개수
다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
다이나믹 메소드 디스패치란?
디스패치는 어떤 메소드를 호출할 것인가를 결정하여 그것을 실행하는 과정이다. 동적 디스패치와 정적 디스패치가 있는데, 동적 디스패치(dynamic dispatch)는 메소드 오버라이딩이 되어있는 경우 실행시점에 어떤 메소드를 실행할 지 결정되는 것이다. 정적 디스패치는 그와 다르게 컴파일 시점에 어떤 메소드를 실행할지 결정된다.
+ 이외에도 더블 디스패치가 존재 한다.
Reference
정적 메소드 디스패치
말 그대로 정적 타이밍(static)에 어떤 메소드를 호출할지 결정하는 과정이다. (컴파일 시점)
메소드를 오버라이딩 하거나 오버로딩 할때도 컴파일 시점에 결정된다.
public class App {
public static void main(String[] args) {
AppService appService = new AppService();
appService.run();
appService.run(2);
}
}
class AppService {
void run() {
System.out.println("run 호출");
}
void run(int num) {
System.out.println("run" + num + "번 호출");
}
}
동적 메소드 디스패치
동적타이밍(Dynamic)에 어떤 메소드를 호출해야 할지 결정하는 과정을 말한다.
즉 런타임 시점에 어떤 메소드를 호출해야 할지 결정되는 과정이다.
인터페이스 또는 추상 클래스를 선언하고, 인터페이스를 구현 및 추상클래스를 상속 받은 하위 클래스를
인스턴스로 생성할 때 발생한다.
public class App {
public static void main(String[] args) {
AppService appService = new subAppService();
appService.run();
AppService appService2 = new subAppService2();
appService2.run();
}
}
abstract class AppService {
abstract void run();
}
class subAppService extends AppService {
@Override
void run() {
System.out.println("sub1");
}
}
class subAppService2 extends AppService {
@Override
void run() {
System.out.println("sub2");
}
}
더블 디스패치 - 토비의 봄 TV 정리
비지터 패턴의 원조 격이 더블 디스패치이다.
instance of를 사용하지 않는다.
=> 1. OCP위반
2. 경우의 수가 변하는 경우 대응이 불가(GooglePlus)
3. 모든 경우의 수를 처리하기 힘듦
동적 디스패치를 두 번하는 기법입니다. (Post중에 어떤 postOn메소드를 선택할지에 대한 dynamic dispatch가 1번, sns.post(this)에서 sns에 대한 dynamic dispatch가 1번 일어나 총 2번)
파라미터는 다이나믹 디스패치의 조건이 되지 않는다.
자바는 싱글 디스패치 언어이다. (receiver가 1개이다.)
public class Dispatch{
interface Post{void postOn(SNS sns);}
static class Text implements Post{
public void postOn(SNS sns){
sns.post(this);
}
}
static class Picture implements Post{
public void postOn(SNS sns){
sns.post(this);
}
}
interface SNS{
void post(Text post);
void post(Picture post);
}
static class Facebook implements SNS{
public void post(Text post){
System.out.println("text -> facebook");
}
public void post(Picture post){
System.out.println("picture -> facebook");
}
}
static class Twitter implements SNS{
public void post(Text post){
System.out.println("text -> twitter");
}
public void post(Picture post){
System.out.println("picture -> twitter");
}
}
//구글 플러스 추가!
static class GooglePlus implements SNS{
public void post(Text post){
System.out.println("text -> gplus");
}
public void post(Picture post){
System.out.println("picture -> gplus");
}
}
public static void main(String[] args){
List<Post> posts = Arrays.asList(new Text(), new Picture());
List<SNS> sns = Arrays.asList(new Facebook(), new Twitter(), new GooglePlus());
/*
for(Post p:posts){
for(SNS s:sns){
p.postOn(s);
}
}
*/
posts.forEach(p->sns.forEach(s.postOn(s)));
}
추상 클래스
특징
abstract keyword를 사용한다.
이름 그대로 구체적이지 않은 클래스이다. => 완성되지 않은 클래스이다.
추상 클래스는 추상메서드를 포함하고 있다는 것을 제외하고는 일반 클래스와 다른것이 없다.
추상메소드는 구현부가 없는 메소드이다. 그리고 중괄호{} 대신 ;을 적어준다.
abstract를 붙여 추상메소드를 선언하는 이유는 자식 클래스에서 추상메소드를 반드시 구현하도록 강요하기 위해서 이다.
추상 클래스는 객체를 생성할 수 없다.
final 키워드
: 변경될 수 없다는 의미를 가진 keyword이며 클래스, 메서드 변수에서 사용 가능하다.
클래스 => 상속을 사용할 수 없다.
메소드 => 오버라이딩을 할 수 없다.
변수 => 값을 변경 할 수 없다. (한번 초기화하면 바꿀 수없다.)
Object 클래스
- 모든 클래스의 부모 클래스이다.
(extends키워드가 없어도 컴파일러가 자동적으로 Object클래스를 상속한다.)
- java.lang.Object 클래스
- 모든 클래스는 Object 클래스의 메서드를 사용할 수 있음
- java lang패키지는 import 안 해도 컴파일러가 자동으로 import 해준다.
- Object 클래스는 총 11개의 메소드로만 구성되어 있다.
toString()메서드의 원형
getClass().getName() + '@' + Integer.toHexString(hashCode())
객체의 정보를 String으로 바꾸어 사용할 때 유용하다.
많은 클래스에서 재정의하여 사용한다.
equals()메서드
물리적으로 다른 메모리에 위치한 객체라도 논리적으로 동일함을 구현하기위해 사용하는 메서드
물리적 동일함 : 같은 주소를 가지는 객체
논리적 동일함 : 같은 학번의 학생, 같은 주문 번호의 주문
hashCode() 메서드
hashCode() 메서드의 반환 값 : 인스턴스가 저장된 가상머신의 주소를 10진수로 반환 (toString으로 반환되는 값과 다름)
두개의 서로 다른 메모리에 위치한 인스턴스가 동일하다는 것은?
-
논리적으로 동일 : equals()의 반환값이 true
-
동일할 hashCode 값을 가짐 : hashCode()의 반환 값이 동일 (통상 equals를 오버라이딩하면 hashCode도 같이 오버라이딩해서 같은 값이 반환될 수 있도록 한다.)
clone() 메소드
객체의 복사본을 만듦
기본 틀(prototype)으로 부터 같은 속성 값을 가진 객체의 복사본을 생성할 수 있음
객체지향 프로그래밍의 정보은닉에 위배되는 가능성이 있으므로 복제할 객체는 cloneable인터페이스 (이런 인터페이스를 마크 인터페이스라고 함)를 명시해야 함
이외에도
finalize() : 힙메모리에서 해제될때 가비지 콜렉터에 의해 수행되는 메소드
wait, notify, notifyAll : 동시성(concurrency)관련 메소드 등이 있다.
Reference
이것이 자바다. (신용권)
multifrontgarden.tistory.com/133
'Java' 카테고리의 다른 글
7주차 과제: 패키지 (0) | 2021.01.01 |
---|---|
6주차 과제: 상속 (feedback, 피드백) (0) | 2020.12.27 |
4주차 과제: 제어문(feedback, 피드백) (0) | 2020.12.22 |
5주차 과제: 클래스(피드백, feedback) (0) | 2020.12.20 |
5주차 과제: 클래스 (0) | 2020.12.14 |