상속(Inheritance)

Agnes Park·2022년 2월 27일
0

JAVA

목록 보기
22/34

1. 상속 (Inheritance)

상위클래스를 상속받아서 하위클래스를 정의하는 방법
class 하위클래스 extends 상위클래스

자바 에선 오로지 '하나의 부모'로부터 상속받을수 있습니다 (단일 상속) 다중 상속 허용하지 않음
(용어)
Super Class(상위 클래스), Parent Class(부모/조상 클래스), Basic Class(기본 클래스)
Sub Class(하위 클래스), Child Class(자식 클래스), Derived Class(유도 클래스)
상속받는다..(동사) inherit , subclass

  • sub class에서는 super class가 가지고 있는 멤버 변수들은 선언하지 않아도 사용할 수 있음
  • super class에 없는 멤버 변수만 선언해 주면 됨

상속의 이점 :

  • 상속을 통하여 기존의 객체를 그대로 활용하면서, 새로운 객체에서
  • 추가, 변경되는 부분만 작성함으로 소프트웨어 개발 효율을 높일수 있다.

[상속 사용하는 경우 예시]

package com.lec.java.inherit02;

public class Inherit02Main {

	public static void main(String[] args) {
		System.out.println("상속 (Inheritance)");

		// BasicTV 클래스의 인스턴스 생성
		BasicTV tv1 = new BasicTV();
		tv1.displayInfo();
		
		System.out.println();

		// SmartTV 클래스의 인스턴스 생성
		SmartTV tv2 = new SmartTV();
		tv2.isPowerOn = true;
		tv2.channel = 100;
		tv2.volume = 10;
		tv2.ip = "192.168.0.110";
		tv2.displayInfo();

		System.out.println("\n프로그램 종료");
	} // end main()
} // end class
package com.lec.java.inherit02;

public class BasicTV {
	// 멤버 변수
	boolean isPowerOn;
	int channel;
	int volume;
	
	// 메소드
	public void displayInfo() {
		System.out.println("--- TV 현재 상태 ---");
		System.out.println("전원: " + isPowerOn);
		System.out.println("채널: " + channel);
		System.out.println("볼륨: " + volume);
	} // end displayInfo()
	
} // class BasicTV
package com.lec.java.inherit02;

// BasicTV
// └ SmartTV
public class SmartTV extends BasicTV{

	// 새로이 추가할 멤버
	String ip;
	
	public void displayInfo() {
		super.displayInfo(); // 부모(super) 의 displayInfo()를 먼저 실행하고
		System.out.println("IP주소: " + ip);	// 추가되는 실행 코드
	}
}

[상속 사용하지 않는 경우 예시]

package com.lec.java.inherit01;

public class Inherit01Main {

	public static void main(String[] args) {
		System.out.println("상속(Inheritance) 을 사용하지 않는 경우");

		// BasicTV의 인스턴스
		BasicTV tv1 = new BasicTV();
		tv1.isPowerOn = true;
		tv1.volume = 10;
		tv1.displayInfo();
		
		// SmartTV의 인스턴스
		SmartTV tv2 = new SmartTV();
		tv2.isPowerOn = true;
		tv2.channel = 123;
		tv2.volume = 12;
		tv2.ip = "192.168.0.111";
		tv2.displayInfo();

		System.out.println("\n프로그램 종료");
	} // end main()
} // end class
package com.lec.java.inherit01;

// 클래스: 멤버변수 (+ 생성자) + 메소드 => 데이터 타입
public class BasicTV {
	// 멤버 변수
	boolean isPowerOn;
	int channel;
	int volume;
	
	// 메소드
	public void displayInfo() {
		System.out.println("--- TV 현재 상태 ---");
		System.out.println("전원: " + isPowerOn);
		System.out.println("채널: " + channel);
		System.out.println("볼륨: " + volume);
	} // end displayInfo()
	
} // end class BasicTV
package com.lec.java.inherit01;

public class SmartTV {
	// 멤버변수
	// 기존의 BasicTV 에 만들었던 멤버들이 그대로 또 작성?
	boolean isPowerOn;
	int channel;
	int volume;
	String ip;	// <-- SmartTV 에서 새로이 추가된 필드
	
	// 메소드
	public void displayInfo() {
		System.out.println("--- TV 현재 상태 ---");
		System.out.println("전원: " + isPowerOn);
		System.out.println("채널: " + channel);
		System.out.println("볼륨: " + volume);
		System.out.println("IP주소: " + ip);	// <- SmartTV 에 추가된 코드
	} // end displayInfo()
}

1. java.lang.Object

  • 자바의 모든 클래스는 java.lang.Object로부터 상속 받는다.
  • java.lang.Object 클래스는 모든 클래스의 부모클래스이다.
  • Object 클래스에 있는 메소드를 다른 클래스에서도 사용 가능
package com.lec.java.inherit03;

public class Inherit03Main {

	public static void main(String[] args) {
		System.out.println("상속 연습");
		System.out.println("java.lang.Object");
		
		Person p1 = new Person();
		p1.name = "홍길동";
		p1.whoAmI();
		
		System.out.println();
		
		BusinessPerson p2 = new BusinessPerson();
		p2.name = "허균";
		p2.whoAmI();
		
		// toString() 은 Object의 메소드
		
		System.out.println(p2);
		System.out.println(p2.toString());
		
		p2.company = "(주)재택";
		p2.showInfo();
		
		
		System.out.println("\n프로그램 종료");
	} // end main()
} // end class
package com.lec.java.inherit03;

public class Person {
	String name;
	
	public void whoAmI() {
		System.out.println("제 이름은 " + name + " 입니다.");
	}

}
package com.lec.java.inherit03;

public class BusinessPerson extends Person {
	String company;
	
	public void showInfo() {
		whoAmI();
		System.out.println("회사는 " + company + " 입니다");
	}
}

2. 상속에서 생성자 호출순서

  1. 자식 클래스의 생성자에서 명시적으로 부모 클래스의 생성자가 호출되지 않으면, 자동으로 부모 클래스의 "디폴트 생성자"가 호출됨
  2. 자식 클래스의 생성자에서 명시적으로 부모 클래스의 생성자를 호출하기도 함
    1) super(...) 키워드 사용 -> 부모 클래스의 생성자를 호출
    2) (주의) super는 항상 제일 처음에 호출되어야 함
    3) 부모 클래스에 디폴트 생성자가 없는 경우도 있을 수 있다.
    -> 그런 경우에는 다른 생성자를 "반드시 명시적으로 호출"해 줘야만 함

어떤 경우에 상속으로 객체를 설계하나?

  • HAS-A 관계 ===> 멤버로 설계
    [Car, Tire]
    Car is-a Tire (X)
    Tire is-a Car (X)
    Car has-a Tire (OK)
  • IS-A 관계 ===> 상속으로 설계
    Vehicle is-a Car (X)
    Car is-a Vehicle (OK)
    HybricCar is-a Car (OK)
package com.lec.java.inherit04;

public class Inherit04Main {

	public static void main(String[] args) {
		System.out.println("상속과 생성자");
		
		System.out.println();
		// Vehicle 클래스의 인스턴스 생성
		Vehicle v1 = new Vehicle();
		
		System.out.println();
		// Car 클래스의 인스턴스 생성
		Car car1 = new Car();
		
		
		
		System.out.println();
		// HybridCar 클래스의 인스턴스 생성
		HybridCar car2 = new HybridCar();
		
		
		System.out.println();
		Car car3 = new Car(450);
		
		System.out.println();
		Car car4 = new Car(100, 6);
		
		System.out.println("\n프로그램 종료");
	} // end main()
} // end class
package com.lec.java.inherit04;

public class Vehicle {

	int speed;
	
	// 생성자
	public Vehicle() {
		System.out.println("Vehicle() 생성");
	}
	
	public Vehicle(int speed) {	// -> 위의 기본생성자 주석처리시 에러 발생. (Implicit super constructor Vehicle() is undefined. Must explicitly invoke another constructor
		this.speed = speed;
		System.out.println("Vehicle(int) 생성: speed=" + speed);
	}
}
 package com.lec.java.inherit04;

public class Car extends Vehicle {

	int oil;
	
	// 생성자
	public Car() {
		// 부모클래스의 기본생성자 호출 --> Vehicle()
		// 명시적으로 super() 가 없으면 기본적으로 부모의 기본생성자 호출
		System.out.println("Car() 생성");
	}
	
	public Car(int oil) {
		// 명시적으로 부모 생성자 호출
		super();	// super는 반.드.시 첫번째 문장이어야 한다. 첫번째줄 아닐시 ERROR (Constructor call must the first statement in a constructor)
		System.out.println("Car(int) 생성: oil= " + oil);
		this.oil = oil;
	}
	
	public Car(int speed, int oil) {
		super(speed);	// Vehicle(int) 호출
		this.oil = oil;
		System.out.println("Car(int,int) 생성: speed=" + speed
				+ "oil=" + oil);
	}
}
package com.lec.java.inherit04;

public class HybridCar extends Car {

	int electricity;
	
	// 생성자
	public HybridCar() {
		System.out.println("HybridCar() 생성");
	}
}

2. 메소드의 재정의(Overriding)

메소드 재정의(Overriding)

  • '상속'관계에서 '부모 클래스에 있던 메소드'를 '재정의'하는 것.
  • 부모 클래스에 있는 메소드와 매개변수 리스트가 동일해야 함
  • 부모 클래스에 있는 메소드와 접근권한 수식어가 동일할 필요는 없지만, 접근권한의 범위가 축소될 수는 없다.
  • 즉, 접근권한은 같거나 더 넓은 수식어를 사용해야 함.
    ! 메소드 오버로딩(Overloading)과 혼돈하지 말자!

final 메소드 : 더이상 오버라이딩 불가
final 클래스 : 더이상 상속 불가

package com.lec.java.inherit07;

public class Inherit07Main {

	public static void main(String[] args) {
		System.out.println("상속: Method Overriding(재정의)");
		
		System.out.println();
		// Person 클래스의 인스턴스 생성
		Person p1 = new Person();
		p1.setName("abc");
		p1.showInfo();
		
		System.out.println();
		// BusinessPerson 클래스의 인스턴스를 생성
		BusinessPerson p2 = new BusinessPerson();
		p2.setName("홍길동");
		p2.setCompany("활빈당");
		p2.showInfo();
		
		// toString() 결과 (java의 객체를 문자열로 표현)
		System.out.println("p1: " + p1);
		System.out.println("p2: " + p2);

		System.out.println("\n프로그램 종료");
	} // end main()
} // end class
package com.lec.java.inherit07;

public class Person {

		private String name;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
		
		protected void showInfo() {
			System.out.println("이름: " + name);
		}
		
		// final 메소드는 더이상 오버라이딩 불가
		public final void whoAreYou() {
			System.out.println("이름: " + name);
		}
}
package com.lec.java.inherit07;

public class BusinessPerson extends Person {

	private String company;

	public String getCompany() {
		return company;
	}

	public void setCompany(String company) {
		this.company = company;
	}
	
	@Override // (권한을 덮어쓰다)
	protected void showInfo() {
//	public void showInfo() { 	// 실행 가능
//	private void showInfo() {	// ERROR: cannot reduce the visibility of the inherited method from Person (접근범위가 더 좁아질 수는 없다)
		super.showInfo();	// 부모(super)의 showInfo() 호출
		System.out.println("회사: " + company);
		
	}

	// 메소드 중복정의(Overloading)
	// 1. 매개변수의 타입이 다르거나
	// 2. 매개변수의 개수가 다를 때
	// 3. 매개변수의 순서를 달리하여
	// 같은 이름으로 (다른 기능을 하는) 메소드를 중복 정의하는 것
	public void showInfo(int id) { 
		System.out.println("id: " + id);
		System.out.println("이름: " + getName());
		System.out.println("회사: " + company);
	}

	// Object 의 메소드들도 오버라이딩 가능
	@Override
	public String toString() {
		return "BusinessPerson:" + getName() + " " + getCompany();
	}
	
	//이클립스에서 
	// ALT + SHIFT + S, V 를 누르면 오버라이드 진행
	//  ※ ALT + SHIFT + S 를 Show Source Quick Menu 라 함
	
//	@Override
//	public void whoAreYou() {	// ERROR : Cannot override the final method from Person.
//		
//	}
	
}
package com.lec.java.inherit07;

//final 이 변수 앞에 붙으면 더이상 변경 불가(상수화)
//final 이 클래스 앞에 붙으면 더이상 상속 불가
//final 이 메소드 앞에 붙으면 더이상 오버라이딩 불가
public final class PostPerson extends Person {

}
package com.lec.java.inherit07;

public class PostBoy /*extends PostPerson*/ {

}

✨TIPs!
1. Open Type Hierarchy (F4) : 클래스명 위 마우스

2. Open Declaration (F3) : 해당하는 클래스로 이동 (선언한 파일 보여줌)

0개의 댓글