상속(Inheritance)

Agnes Park·2022년 2월 27일
0

JAVA

목록 보기
22/34
post-custom-banner

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) : 해당하는 클래스로 이동 (선언한 파일 보여줌)

post-custom-banner

0개의 댓글