JAVA 6주차

ndy·2022년 10월 10일

Java

목록 보기
6/10

상속

  • 현실 세계
    • 부모가 자식에게 물려주는 행위
    • 부모가 자식을 선택해서 물려줌
  • 객체 지향 프로그램
    • 자식 클래스가 부모 클래스의 맴버를 물려받는 것
    • 상속 대상 : 부모의 필드와 메소드
  • 상속의 효과
    • 부모 클래스를 재사용하여 자식 클래스를 빨리 개발 가능
    • 반복된 코드의 중복을 줄여줌
    • 유지 보수의 편리성을 제공
    • 객체의 다형성을 구현할 수 있음
  • 상속 대상의 제한
    • 부모 클래스의 private 접근을 갖는 필드와 메소드는 제외됨
    • 부모 클래스가 다른 패키지에 있는 경우, default 접근을 갖는 필드와 메소드는 제한됨
public class A {
	int field1;
    void method(){...}
}
public class B extends A {
	String field2;
    void method2(){...}
}

자바는 다중 상속 허용 x


자식 객체를 생성하면 부모 객체도 생성되는가?

  • 자식 객체를 생성할 때는 부모 객체부터 생성되고 자식 객체가 생성된다.
  • 부모 생성자가 호출 완료되고, 자식 생성자가 나중에 호출 완료된다.
public class DmbCellPhone extends CellPhone {}
DmbCellPhone dmbCellPhone = new DmbCellPhone();


명시적으로 부모 생성자 호출

  • 부모 객체를 생성할 때, 부모 생성자를 선택해서 호출 할 수 있음
자식 클래스( 매개변수 선언,...) {
	super(매개값,...); // 매개변수가 있는 부모 생성자 호출 가능
}
  1. 반드시 자식 생성자의 첫줄에 위치해야 함
  2. 부모 클래스에 기본(매개변수가 없는) 생성자가 없다면 필수적으로 작성해야 한다.

메소드 재정의 (Override)

  • 부모 클래스의 상속 메소드를 수정해서 자식 클래스에서 재정의하는 것을 말함
  • 메소드 재정의 조건
    • 부모 클래스의 메소드 선언부와 동일해야 함
    • 접근 제한을 더 강하게 오버리딩 할 수 없음
      • publicdefaultprivate로 수정 불가능
      • defaultpublic으로 수정 가능

@Override 어노테이션

  • 컴파일러에게 부모 클래스의 메소드와 선언부가 동일한지 검사하도록 지시
public class Computer extends Calculator {
	@Override
    double areaCircle(double r) { // 선언부가 정확한지 확인
    	System.out.println("Computer 객체의 areaCircle() 실행");
        return Math.PI * r * r;
    }
}

메소드 재정의 효과

  • 부모 메소드는 숨겨지는 효과 발생
    • 재정의된 자식 메소드가 실행

부모 메소드 사용 (super)

  • 메소드 재정의는 부모 메소드를 숨기는 효과
    • 자식 클래스에서는 재정의된 메소드만 호출됨
  • 자식 클래스에서 수정되기 전의 부모 메소드를 호출하고자 할 경우 super를 사용
    • super는 부모 객체를 참조(this는 자신 객체를 참조)


final 클래스와 final 메소드

final 키워드의 용도

  • final 필드 : 수정할 수 없는 필드
  • final 클래스 : 부모로 사용할 수 없는 클래스 (상속 불가능)
  • final 메소드 : 자식이 재정의할 수 없는 메소드

상속할 수 없는 final 클래스

  • 자식 클래스를 만들 수 없도록 final 클래스로 만듦
public final class A {}
public class B extends A {} // final 클래스는 상속 불가능

오버라이딩 할 수 없는 final 메소드

  • 자식 클래스가 재정의 못하도록 부모 클래스의 메소드를 final로 만듦
public final int Add(num1, num2){}

protected 접근 제한자

  • 상속과 관련된 접근 제한자
    • 같은 패키지 : default와 동일
    • 다른 패키지 : 자식 클래스만 접근 허용

package1

public class A {
	protected int num;
}
class B {
	A a1 = new A();
	a1.num = 1;	// 같은 패키지이므로 가능
}

package2

class C {
	A a2 = new A();
    a2.num = 2; // 다른 패키지이므로 불가능
}

class D extends A {
	A a3 = new A();
    a3.num = 3; // 다른 패키지이지만 자식 클래스이므로 가능
}

타입변환과 다형성

다형성

  • 같은 타입이지만 실행 결과가 다양한 객체를 대입(이용)할 수 있는 성질을 말함
    • 부모 타입에는 모든 자식 객체가 대입될 수 있음
      • 자식 타입은 부모 타입으로 자동 타입 변환됨
    • 객체를 부품화 시킬 수 있음
public class Tire {}

class Tire1 extends Tire {}
class Tire2 extends Tire {}
Tire a = new Tire1();
Tire a = new Tire2();

자동 타입 변환

  • 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말함
cat == animal // true

  • 상속 계층에서 어떤 상위 타입이라도 자동 타입 변환이 일어날 수 있음

  • 자동 타입 변환된 이후의 효과
    • 부모 클래스에 선언된 필드와 메소드만 접근 가능
    • 메소드가 재정의되었다면 자식 클래스의 재정의된 메소드가 호출 됨
class Parent {
	void method1(){}
    void method2(){}
}
class Child extends Parent {
	void method2() {...} // Overriding
    void method3() {}
}
class ChileEx {
	public static void main(String[] args) {
    	Child child = new Child();
        
        Parent parent = child; // 가능
        parent.method1();	// Parent 클래스의 method1() 호출
       	parent.method2();	// Child 클래스의 재정의된 method2() 호출 [중요]
        parent.method3();	// 호출 불가
    }
}

필드의 다형성

  • 다형성을 구현하는 기술적 방법
    1. 부모 타입으로 자동 변환
    2. 재정의된 메소드(오버라이딩)

Car.class

public class Car {
	Tire frontLeftTire = new Tire();
    Tire frontRightTire = new Tire();
    Tire backLeftTire = new Tire();
    Tire backRightTire = new Tire();
    
    void run() {
    	frontLeftTire.roll();
        frontRightTire.roll();
        backLeftTire.roll();
        backRightTire.roll();
    }
}

HankookTire.class

public class HankookTire extends Tire {
	void roll(){...} // 재정의된 메소드
}

KumhoTire.class

public class KumhoTire extends Tire {
	void roll(){...} // 재정의된 메소드
}

Exe.class

Car myCar = new Car();
myCar.frontRightTire = new HankookTire();	// HankookTire 객체 
myCar.backLeftTire = new KumhoTire();
myCar.run();
//HankookTire 클래스에서 재정의된 roll() 메소드 호출
//KumhoTire 클래스에서 재정의된 roll() 메소드 호출

하나의 배열로 객체 관리

public class Car {
	Tire[] tires = {
    	new Tire("앞 왼쪽", 6),
        new Tire("앞 오른쪽", 2),
        new Tire("뒤 왼쪽", 3),
        new Tire("뒤 오른쪽", 4)
    };
}
tires[1] = new KumhoTire("앞 오른쪽", 13); // 자동 타입 변환

매개변수의 다형성

  • 매개변수가 클래스 타입일 경우 해당 클래스의 객체를 대입하는 것이 원칙이나 자식 객체를 대입하는 것도 허용됨
public class Vehicle {
	public void run() {
    	system.out.println("차량");
    }
}
public class Driver {
	void drive(Vehicle vehicle){
    	vehicle.run();
    }
}
public class Bus extends Vehicle{
	public void run() {
    	System.out.println("버스"); // Vehicle 클래스의 run() 메소드 재정의
    }
}
Driver driver = new Driver();
Bus bus = new Bus();

driver.drive(bus); // Bus 클래스에서 재정의한 run 메소드 실행

강제 타입 변환

  • 부모 타입을 자식 타입으로 변환하는 것을 말함
자식클래스 변수 = (자식클래스) 부모클래스 타입;
  • 조건
    • 자식 타입이 부모 타입으로 자동 변환된 이후
      A a = new B();	// 부모클래스 타입으로 자동 변환
      B b = a;	// 불가능
      B b = (B) a; // 자식 타입이 부모 타입으로 변환된 이후 다시 강제 변환 가능
  • 강제 타입 변환이 필요한 경우
    • 자식 타입이 부모 타입으로 자동 변환되면, 부모 타입에 선언된 필드와 메소드만 사용 가능
    • 자식 타입에 선언된 필드와 메소드를 다시 사용해야 한다면 강제 타입 변환이 필요

객체 타입 확인

  • 부모 타입이면 모두 자식 타입으로 강제 타입 변환할 수 있는 것은 아님
    • ClassCastException 예외가 발생 가능
Parent parent = new Parent();
Child child = (Child) parent; // 강제 타입 변환 불가능
  • 먼저 자식 타입인지 확인 후 강제 타입 변환 해야 함
boolean result = (객체) instanceof (타입) // (객체)가 (타입)이면 true

추상클래스의 개념

  • 추상
    • 실체들 간에 공통되는 특성을 추출한 것
      • ex) 새, 곤충, 물고기 -> 동물(추상)
  • 추상 클래스
    • 실체 클래스들의 공통되는 필드와 메소드를 정의한 클래스
    • 추상 클래스는 실체 클래스의 부모 클래스 역할을 할 수 있음
    • 추상 클래스는 단독으로 객체 생성이 불가능
Animal animal = new Animal(); // 객체 생성이 불가능

class Ant extends Animal {} // 상속 가능

추상 클래스의 용도

  • 실체 클래스의 공통된 필드와 메소드의 이름을 통일할 목적
  • 실체 클래스를 작성할 때 시간을 절약
    • 실체 클래스는 추가적인 필드와 메소드만 선언하면 됨

추상 클래스 선언

public abstract class A {
	//필드
    //생성자
    //메소드
}

추상 메소드와 오버라이딩(재정의)

  • 메소드의 이름은 동일하나, 실행 내용이 실체 클래스 마다 다른 메소드가 있을 수 있음
public abstract class Animal {
	public abstract void sound();
}
public class Dog extends Animal {
	@Override
    public void sound() {
    	System.out.println("멍멍");
    }
}
public class Cat extends Animal {
	@Override
    public void sound() {
    	System.out.println("야옹");
    }
}

0개의 댓글