[혼공자]4주차

박수연·2025년 8월 3일
0

[혼공자]

목록 보기
4/7

07 상속

07-1 상속

  • 상속 : 부모가 자식에게 물려주는 행위
  • 프로그램에서 부모 클래스를 상위 클래스라 부르고 자식 클래스를 하위 클래스 또는 파생클래스라고 부름
  • 객체지향에서 상위(부모) 클래스의 멤버를 하위(자식) 클래스에 물려줄 수 있다

클래스 상속

  • 프로그램에서는 자식이 부모를 선택, 자식 클래스를 선언 할 때 어떤 부모의 클래스를 상속받을 것인지 결정
class 자식클래스 extends 부모클래스 {
	// 필드
    // 생성자
    // 메소드
}
  • 상속의 특징 :
    ① 하나의 부모 클래스만 상속받을 수 있다
    ② 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속에서 제외된다
    부모 클래스가 다른 패키지에 있다면 default 접근 제한을 갖는 필드와 메소드도 상속에서 제외된다

부모 생성자 호출

  • 자바에서 자식 객체를 생성하면 부모 객체 먼저 생성된 후 자식 객체가 생성된다
  • 자식 클래스에서 부모 클래스의 생성자는 자식 생성자의 맨 첫줄에서 호출, 명시적으로 선언되지 않을 경우 기본 생성자 자동 생성

메소드 재정의

  • 상속된 메소드가 자식 클래스에서 사용하기 적합하지 않을 경우, 자식 클래스에서 수정해서 사용하는것

메소드 재정의 방법

  • 규칙
    • 부모의 메소드와 동일한 리턴 타입, 메소드 이름, 매개 변수 목록을 가져야 한다
    • 접근 제한을 더 강하게 재정의 할 수 없다(반대로는 가능 public -> default, private 안됨, default -> public 가능)
    • 새로운 예외(Exception)를 throws 할 수 없다

부모 메소드 호출

  • 자식 클래스 내부에서 부모 클래스의 메소드를 호출 할 때 super 키워드를 붙여 호출 가능
    super.부모메소드();

final 클래스와 final 메소드

  • 필드 선언시 final이 지정되면 초기값 설정 후 값을 변경 할 수 없다

상속할 수 없는 final 클래스

  • final 클래스는 자식 클래스를 만들 수 없다(상속 불가)
    public final class 클래스 { … }

재정의 할 수 없는 final 메소드

  • 부모 클래스를 상속해 자식 클래스를 선언 할 때 부모 클래스에서 선언된 final 메소드는 자식 클래스에서 재정의 할 수 없다
    public final class 클래스 { … }

★protected 접근 제한자
protected는 public과 default 접근 제한자의 중간쯤에 해당
protected 접근 제한자가 붙은 클래스는 같은 패키지 내에서는 접근 제한이 없지만, 다른 클래스일 경우 자식 클래스만 접근을 허용

07-2 타입 변환과 다형성

  • 다형성 : 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질

자동 타입 변환

  • 프로그램 실행 도중 자동적으로 타입 변환이 일어나는 것
  • 자식은 부모 타입으로 자동 타입 변환이 가능
  • 바로 위 부모가 아니더라도 상속 계층에서 상위 타입이면 자동 타입 변환이 일어날 수 있다

필드의 다형성

  • 필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들을 저장 가능하므로 다양한 형태의 필드를 가질 수 있게 된다

Tire 클래스

public class Tire {
	//필드
	public int maxRotation;     			//최대 회전수(최대 수명)
	public int accumulatedRotation;			//누적 회전수
	public String location;       			//타이어의 위치

	//생성자
	public Tire(String location, int maxRotation) {
		this.location = location;
		this.maxRotation = maxRotation;
	}

	//메소드
	public boolean roll() {
		++accumulatedRotation;		
		if(accumulatedRotation<maxRotation) {
			System.out.println(location + " Tire 수명: " + (maxRotation-accumulatedRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " Tire 펑크 ***");
			return false;
		}
	}
}

Car 클래스

public class Car {
	//필드
	Tire frontLeftTire = new Tire("앞왼쪽", 6);
	Tire frontRightTire = new Tire("앞오른쪽", 2);
	Tire backLeftTire = new Tire("뒤왼쪽", 3);
	Tire backRightTire = new Tire("뒤오른쪽", 4);
	
	//생성자
	
	//메소드
	int run() {
		System.out.println("[자동차가 달립니다.]");
		if(frontLeftTire.roll()==false) { stop(); return 1; };
		if(frontRightTire.roll()==false) { stop(); return 2; };
		if(backLeftTire.roll()==false) { stop(); return 3; };
		if(backRightTire.roll()==false) { stop(); return 4; };
		return 0;
	}
	
	void stop() {
		System.out.println("[자동차가 멈춥니다.]");
	}
}

HankookTire, KumhoTire 클래스

public class HankookTire extends Tire {
	//필드
	//생성자
	public HankookTire(String location, int maxRotation) {
		super(location, maxRotation);
	}	
	//메소드
	@Override
	public boolean roll() {
		++accumulatedRotation;		
		if(accumulatedRotation<maxRotation) {
			System.out.println(location + " HankookTire 수명: " + (maxRotation-accumulatedRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " HankookTire 펑크 ***");
			return false;
		}
	}
}
public class KumhoTire extends Tire {
	//필드
	//생성자
	public KumhoTire(String location, int maxRotation) {
		super(location, maxRotation);
	}	
	//메소드
	@Override
	public boolean roll() {
		++accumulatedRotation;		
		if(accumulatedRotation<maxRotation) {
			System.out.println(location + " KumhoTire 수명: " + (maxRotation-accumulatedRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " KumhoTire 펑크 ***");
			return false;
		}
	}
}

CarExample 클래스

public class CarExample {
	public static void main(String[] args) {
		Car car = new Car();
		
		for(int i=1; i<=5; i++) {
			int problemLocation = car.run();
			switch(problemLocation) {
				case 1:
					System.out.println("앞왼쪽 HankookTire로 교체");
					car.frontLeftTire = new HankookTire("앞왼쪽", 15);
					break;
				case 2:
					System.out.println("앞오른쪽 KumhoTire로 교체");
					car.frontRightTire = new KumhoTire("앞오른쪽", 13);	
					break;
				case 3:
					System.out.println("뒤왼쪽 HankookTire로 교체");
					car.backLeftTire = new HankookTire("뒤왼쪽", 14);	
					break;
				case 4:
					System.out.println("뒤오른쪽 KumhoTire로 교체");
					car.backRightTire = new KumhoTire("뒤오른쪽", 17);		
					break;
			}
			System.out.println("----------------------------------------");
		}
	}
}
  • Tire, Car, HankookTire, KumhoTire 클래스를 이용한 실행 클래스
  • 3번째 줄에서 Car 객체 생성, for문에서 반복하면서 run메소드 호출하고 펑크 난 타이어 번호를 리턴한다
  • 10, 14, 19, 21번째 라인에서 Car객체의 Tire필드에 HankookTire와 KumhoTire 객체를 대입한다(자동 타입 변환)
  • 이 클래스를 실행하면 앞오른쪽 타이어의 최대 회전수가 2이므로 2번째 roll()호출에서 펑크가 나고 자동차는 멈추게 된다
  • 이후 앞오른쪽 타이어를 KumhoTire로 교체하고 다시 움직인다

매개 변수의 다형성

  • 매개값을 다양화 하기 위해 배개 변수에 자식 객체를 지정할 수도 있다
  • 매개값으로 어떤 자식 객체가 제공되느냐에 따라 메소드의 실행결과가 다양해질 수 있다

강제 타입 변환

  • 부모 타입을 자식 타입으로 변환하는것
  • 자식 타입이 부모 타입으로 자동 타입 변환한 후 다시 자식 타입으로 변환할 때 강제 타입변환을 사용할 수 있다
    자식 타입 변수 = (자식타입) 부모타입;
    Parent parent = new Child(); // 자동 타입 변환
    Child child = (Child) parent; // 강제 타입 변환

객체 타입 확인

  • 객체의 타입을 확인할 때 instanceof 연산자 사용
    boolean result = 좌항(객체) instanceof 우향(타입)
  • 주로 매개값의 타입을 조사할 때 사용

07-3 추상 클래스

  • 객체를 직접 생성할 수 있는 클래스의 공통적인 특성(필드, 메소드)을 추출하여 선언한 클래스를 추상클래스라 한다

추상 클래스의 용도

공통된 필드와 메소드의 이름을 통일할 목적

  • 실체 클래스를 여러 사람이 설계할 경우, 클래스마다 필드와 메소드의 이름이 다를 수 있기 때문에 상속을 이용하여 필드와 메소드 이름을 통일할 수 있다

실체 클래스를 작성할 때 시간 절약

  • 공통적인 필드와 메소드는 추상 클래스에 모두 선언해두고, 다른점만 실체 클래스에 선언하면 시간을 절약할 수 있다

추상 클래스 선언

  • 추상 클래스 선언 시 abstract 키워드를 붙인다
public abstract class 클래스 {
	//필드
	//생성자
	//메소드
}

추상 메소드와 재정의

  • 추상 메소드는 abstract 키워드와 함께 메소드의 선언부만 있고 실행 내용은 없는 메소드이다
[public | protected] astract 리턴타입 메소드이름(매개변수, …);
  • 추상 메소드는 하위 클래스에서 반드시 실행 내용을 채워야 한다 그렇지 않을 경우 컴파일 에러가 발생한다

과제

  • 기본과제
    용어 정리를 하면서 공부를 하지만 이 중에서도 중요하다 생각되는 단어들을 몇개 추려봤습니다
    - 클래스 상속 : 부모의 특성을 물려받는것으로 프로그램에서는 자식이 부모를 선택, 자식 클래스를 선언 할 때 어떤 부모의 클래스를 상속받을 것인지 결정한다
    - 메소드 재정의 : 상속된 메소드가 자식 클래스에서 사용하기 적합하지 않을 경우, 자식 클래스에서 수정해서 사용하는것
    - final 클래스 : 상속이 불가능한 클래스(자식 클래스를 만들 수 없음), 필드 선언시 final이 지정되면 초기값 설정 후 값을 변경 할 수 없다
    - final 메소드 : 부모 클래스를 상속해 자식 클래스를 선언 할 때 부모 클래스에서 선언된 final 메소드는 자식 클래스에서 재정의 할 수 없다
    - 다형성 : 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질
    - 자동 타입 변환 : 프로그램 실행 도중 자동적으로 타입 변환이 일어나는 것, 자식은 부모 타입으로 자동 타입 변환이 가능, 바로 위 부모가 아니더라도 상속 계층에서 상위 타입이면 자동 타입 변환이 일어날 수 있다
    - 필드의 다형성 : 필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들을 저장 가능하므로 다양한 형태의 필드를 가질 수 있게 된다
    - 추상클래스 : 객체를 직접 생성할 수 있는 클래스의 공통적인 특성(필드, 메소드)을 추출하여 선언한 클래스(하나 이상의 추상 메소드를 가진 클래스)
    - 추상 클래스의 용도 : ①공통된 필드와 메소드의 이름을 통일할 목적 ②실체 클래스를 작성할 때 시간 절약

넷째주 느낀점
방학전에 내주신 숙제를 방학 숙제로 만들어버렸다
안그러기로 했지만 내 마음속에는 게으른 악마가 살고있는게 틀림없는것 같다
난 항상 그 악마의 속삭임에 넘어가는 한없이 나약한 인간이다

0개의 댓글