본문 바로가기
Programming/Java프로그래밍및실습

[자프실] 5. 상속

by Lizardee 2024. 1. 5.
5.1 상속의 개념
상속의 필요성

상속의 필요성

 


5.2 클래스 상속 & 객체
자바의 상속 선언

자바의 상속 선언

 

상속과 객체
/*
 * 예제 5-1
 * (x,y)의 한 점을 표현하는 Point 클래스
 * Point 클래스를 상속받아 점에 색을 추가한 ColorPoint 클래스
 */

// Point 클래스
class Point{
	private int x, y;
	
	public void set(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	public void ShowPoint() {
		System.out.println("(" + x + ", " + y + ")");
	}
}

// ColorPoint 클래스
class ColorPoint extends Point{
	String color;
	
	public void setColor(String c) {
		this.color = c;
	}
	
	public void showColorPoint() {
		System.out.print(color);
		ShowPoint();
	}
}


public class ColorPointEx {
	public static void main(String[] args) {
		Point p = new Point();
		p.set(1, 2);
		p.ShowPoint();
		
		ColorPoint cp = new ColorPoint();
		cp.set(2, 3);
		cp.setColor("red");
		cp.showColorPoint();
	}
}

 

자바 상속의 특징
  • 자바에서는 클래스의 다중 상속(multiple inheritance)을 지원하지 않는다.
    • cf) 인터페이스(interface): 다중으로 상속받아 구현할 수 있다.
  • 자바의 모든 클래스는 자바에서 제공하는 Object 클래스를 자동으로 상속받도록 컴파일된다.

 


5.3 protected 접근 지정
슈퍼 클래스의 디폴트 멤버에 대한 서브 클래스의 접근

슈퍼클래스 멤버에 대한 접근 지정

 

protected 멤버

슈퍼 클래스 멤버에 대한 서브 클래스의 접근

 


5.4 상속 & 생성자
서브 클래스와 슈퍼 클래스의 생성자 호출 및 실행
  • 서브클래스 객체가 생성될 때, 서브클래스의 생성자와 슈퍼클래스의 생성자가 모두 실행된다.
  • 서브클래스의 생성자와 슈퍼클래스의 생성자 중 슈퍼클래스의 생성자가 먼저 실행된다.

 

서브 클래스에서 슈퍼 클래스 생성자 선택
  • 슈퍼클래스의 기본 생성자가 묵시적으로 선택
  • super()를 이용하여 명시적으로 슈퍼클래스의 생성자 선택
/*
 * 예제 5-2
 * super()를 활용한 ColorPoint 작성
 */

class Point{
	private int x, y;
	
	public Point (int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	public void showPoint() {
		System.out.println("("+x+", "+y+")");
	}
}

class ColorPoint extends Point{
	private String color;
	
	public ColorPoint(int x, int y, String color) {
		super(x,y);  // Point의 생성자 Point(x,y) 호출
		this.color = color;
	}
	
	public void showColorPoint() {
		System.out.print(color);
		showPoint();
	}
}

public class SuperEx {
	public static void main(String[] args) {
		ColorPoint cp = new ColorPoint(5, 6, "blue");
		cp.showColorPoint();
	}
}

 


5.5 업캐스팅 &  instanceof 연산자

▶ 캐스팅(casting): 타입 변환

  • 업캐스팅(upcastting)
  • 다운캐스팅(downcasting)
업캐스팅

업캐스팅 - 사례

 

다운캐스팅

: 업캐스팅된 것을 원래대로 되돌리는 것

 

instanceof 연산자와 객체 구별

instanceof 연산자와 객체 구별

--> instanceof 연산자 사용

 

/*
 * 예제 5-3
 * instanceof 연산자 활용
 */
class Person{}
class Student extends Person{}
class Researcher extends Person{}
class Professor extends Researcher{}

public class InstanceOfEx {
	static void print(Person p) {
		if(p instanceof Person) {
			System.out.print("Person");
		}
		if(p instanceof Student) {
			System.out.print("Student");
		}
		if(p instanceof Researcher) {
			System.out.print("Researcher");
		}
		if(p instanceof Professor) {
			System.out.print("Professor");
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		System.out.print("new Student() -> ");
		print(new Student());
		
		System.out.print("new Reasercher() -> ");
		print(new Researcher());
		
		System.out.print("new Professor() -> ");
		print(new Professor());
	}
}

 


5.6 메소드 오버라이딩
메소드 오버리이딩의 개념

: 서브 클래스에서 슈퍼 클래스에 선언된 메소드를 중복 작성하여, 슈퍼 클래스에 작성된 메소드를 무력화시키고, 객체의 주인 노릇을 하는 것

--> 슈퍼 클래스의 레퍼런스를 이용하든, 서브 클래스의 레퍼런스를 이용하든 항상 서브 클래스에 오버리이딩한 메소드가 실행된다.

오버라이딩

 

오버라이딩의 목적, 다형성 실현
  • 오버라이딩의 목적: 슈퍼클래스에서 선언된 메소드를, 동일한 이름으로 각 서브클래스에서 필요한 내용으로 새로 구현한다. (다형성 실현)
/*
 * 예제 5-4
 * 메소드 오버라이딩으로 다형성 실현
 */

class Shape{
	public void draw() {
		System.out.println("Shape");
	}
}

class Line extends Shape{
	public void draw() {
		System.out.println("Line");
	}
}

class Rect extends Shape{
	public void draw() {
		System.out.println("Rect");
	}
}

class Circle extends Shape{
	public void draw() {
		System.out.println("Circle");
	}
}

// 메인 클래스
public class MethodOverridingEx {
	static void paint(Shape p) {  // paint
		p.draw();
	}
	
	public static void main(String[] args) {
		Line line = new Line();
		paint(line);  // Line의 draw 실행
		System.out.println();
		
		paint(new Shape());
		paint(new Line());
		paint(new Rect());
		paint(new Circle());
	}
}

 

동적 바인딩(dynamic binding)

: 실행할 메소드를 컴파일 시(compile time)에 결정하지 않고, 실행 시(run time)에 결정하는 것

동적 바인딩 - 오버라이딩된 메소드를 호출한다.

 

오버라이딩과 super 키워드

: 클래스에서 super 키워드를 이용하면 정적 바이딩을 통해 슈퍼클래스의 멤버에 접근할 수 있다.

super를 이용한 슈퍼클래스 멤버 접근

 

오버로딩(overloading)과 오버라이딩(overriding)
  • 오버라이딩(overriding): 슈퍼클래스에 있는 메소드, 이름, 매개변수 타입과 개수, 리턴 타입 등이 모두 동일한 메소드가 서브 클래스에 재정의되는 것
  • 오버로딩(overloading): 한 클래스나 상속 관계에 있는 클래스에 서로 매개 변수 타입이나 개수가 다른 여러 개의 메소드가 같은 이름으로 작성되는 것

 

 


5.7 추상 클래스(abstract class)
추상 메소드(abstract method)

: abstract 키워드와 함께 원형만 선언되고, 코드는 작성되지 않은 메소드

추상 메소드(abstract method)

 

추상 클래스 선언

: abstract로 선언한 클래스

추상 클래스 선언

 

추상 클래스의 인스턴스를 생성할 수 없다

: 응용프로그램에서는 추상 클래스의 인스턴스(객체)를 생성할 수 없다. 이는 추상 클래스에는 실행 코드가 없는 미완성 상태인 추상 메소드가 있을 수 있기 때문이다.

 

추상 클래스 상속과 구현

▶ 추상 클래스의 상속

: 추상 메소드를 추상 클래스를 상속받는 서브 클래스는 자동으로 추상 클래스가 된다. 이는 추상 메소드를 상속받기 때문이다. 그러므로 서브 클래스에 abstract를 붙여 추상 클래스임을 명시해야 한다.

추상 클래스의 상속

 

▶ 추상 클래스의 구현

: 서브클래스에서 슈퍼클래스의 모든 추상 메소드를 오버라이딩하여 실행 가능한 코드로 구현하는 것

 

추상 클래스의 목적

: 슈퍼클래스로 활용하기 위함

예제 5-5: 추상 클래스의 구현
예제 5-5: 추상 클래스의 구현

 


5.8 인터페이스

: 서로 다른 하드웨어 장치들이 상호 데이터를 주고받을 수 있는 규격

 

자바 인터페이스

자바 인터페이스 - 사례

 

인터페이스의 객체는 생성할 수 없다

: 인터페이스는 객체를 생성할 수 없다.

인터페이스의 객체는 생성할 수 없다

 

인터페이스 상속

: 인터페이스는 다른 인터페이스를 상속할 수 있다.

 

인터페이스 구현

: implements 키워드를 사용하여 인터페이스의 모든 추상 메소드를 구현한 클래스를 작성하는 것

/*
 * 예제 5-6
 * PhoneInterface 인터페이스를 구현하고, flash() 메소드를 추가한 SamsungPhoen 클래스
 */

// PhoneInterface 인터페이스 선언
interface PhoneInterface {
	final int TIMEOUT = 10000;
	void sendCall();
	void receiveCall();
	default void printLogo() {
		System.out.println("**Phone**");
	}
}

// SamsungPhone 인터페이스 구현
class SamsungPhone implements PhoneInterface{
	@Override
	public void sendCall() {
		System.out.println("띠리링");
	}
	
	@Override
	public void receiveCall() {
		System.out.println("전화가 왔습니다.");
	}
	
	// 메소드 추가 작성
	public void flash() {
		System.out.println("전화기에 불이 켜졌습니다.");
	}
}

public class InterfaceEx {
	public static void main(String[] args) {
		SamsungPhone phone = new SamsungPhone();
		phone.printLogo();
		phone.sendCall();
		phone.receiveCall();
		phone.flash();
	}
}

 

클래스 상속과 함께 인터페이스 구현
/*
 * 예제 5-7
 * 클래스 상속과 함께 인터페이스 구현 사례
 */

interface PhoneInterface{
	final int TIMEOUT = 10000;
	void sendCall();
	void receiveCall();
	default void printLogo() {
		System.out.println("**Phone**");
	}
}

class Calc{
	public int calculate(int x, int y) {
		return x+y;
	}
}

// extends Calc, implements PhoneInterface
class SmartPhone extends Calc implements PhoneInterface{
	// PhoneInterface의 추상 메소드 구현
	@Override
	public void sendCall() {
		System.out.println("따르릉");
	}
	@Override
	public void receiveCall() {
		System.out.println("전화 왔어요.");
	}
	
	// 추가로 작성한 메소드
	public void schedule() {
		System.out.println("일정 관리합니다.");
	}
}

public class PhoneInterfaceEx {
	public static void main(String[] args) {
		SmartPhone phone = new SmartPhone();
		phone.printLogo();
		phone.sendCall();
		phone.receiveCall();
		System.out.println("3과 5를 더하면 " + phone.calculate(3, 5));  // extends Calc
		phone.schedule();
	}
}