[TIL] PowerJava chap6 - 상속

은동·2023년 1월 30일
0

JAVA_TIL

목록 보기
6/8
post-thumbnail

✔️ 상속(inheritance)

기존에 존재하는 클래스로부터 필드와 메소드를 이어받고, 필요한 기능을 추가할 수 있는 기법

검증된 소프트웨어를 재사용하여 신뢰성 있는 소프트웨어를 손쉽게 개발, 유지 보수 할 수 있게 해줌

  • 상속의 형식
    extends 키워드를 이용하여 상속을 나타냄
class Car {
	int speed;
    public void setSpeed(int speed)	{
		this.speed = speed;
}

class ElectricCar extends Car{
	int batteryLevel;
    
    public void charge(int mount){
		batteryLevel +=amount;
    }
}

public class ElectricCarTest{
	public static void main(String[] args){
    	ElectricCar obj = new ElectricCar();
        // 자식 클래스 객체 생성
        obj.speed = 10;	// 부모 클래스의 필드와 메소드 이용
        obj.setSpeed(60);	// 부모 클래스의 필드와 메소드 이용	
        obj.charge(10);	// 자체 메소드 사용
    }
}

+) UML을 이용하여 상속을 나타낼 때에는 화살표가 자식 클래스에서 부모 클래스로 향함

✔️ 자바 상속의 특징

  1. 다중 상속(여러 개의 클래스로부터 상속)을 지원하지 않는다.
  2. 상속의 횟수에는 제한이 없다.
  3. 상속 계층 구조의 최상위에는 java.lang.Object 클래스가 있다.
  • java.lang 패키지 ?
    자바에서 가장 기본적인 동작을 수행하는 클래스들의 집합
    따라서 import문을 사용하지 않더라도 바로 이름만으로 클래스 사용 가능
  • java.lang.Object 클래스 ?

모든 자바 클래스의 최고 조상 클래스

모든 자바 클래스는 Object클래스의 모든 메소드를 바로 사용 가능

클래스를 선언할 때 extends 키워드로 다른 클래스를 상속하지 않으면 암묵적으로 java.lang.Object클래스를 상속하게 됨

출처 - https://jocoma.tistory.com/entry/javalang-%ED%8C%A8%ED%82%A4%EC%A7%80

✔️ 상속과 접근 지정자

자식 클래스는 부모 클래스의 public멤버, protected멤버, 디폴트 멤버(부모 클래스와 자식 클래스가 같은 패키지에 있다면)를 상속받는다. 하지만 부모 클래스의 private멤버는 상속되지 않음

접근 지정자동일한 클래스동일한 패키지자식 클래스다른 패키지
publicOOOO
protectedOOOX
privateOXXX
defaultOOOX

✔️ 상속과 생성자

자식 클래스의 객체가 생성될 때, 자식 클래스의 생성자만 호출될까?
결론은 부모 클래스의 생성자도 호출된다.

class Base {
	public Base() {
		System.out.println("Base() 생성자");
	}
}
class Derived extends Base{
	public Derived() {
		System.out.println("Derived() 생성자");
	}
}
public class Test {

	public static void main(String[] args) {
		Derived r = new Derived();
	}

}

출력 결과 :
Base() 생성자
Derived() 생성자

  • 왜 ?
    자식 클래스 안에는 부모 클래스에서 상속된 부분이 들어 잇다. 따라서 자식 클래스 안의 부모 클래스 부분을 초기화하기 위해 부모 클래스의 생성자도 호출되는 것
  • 호출 순서
    부모 클래스의 생성자 -> 자식 클래스의 생성자


✔️ 명시적인 호출

자식 클래스의 생성자에서 명시적으로 부모 클래스의 생성자를 호출할 수 있는데, 이 때 super키워드를 사용한다.

class Base {
	public Base() {
		System.out.println("Base() 생성자");
	}
}
class Derived extends Base{
	public Derived() {
		super();
		System.out.println("Derived() 생성자");
	}
}

✔️ 묵시적인 호출

자바에서는 명시적으로 부모 클래스의 생성자를 호출해주지 않아도 자식 클래스의 객체가 생성될 때 자동적으로 부모 클래스의 기본 생성자가 됨

class Base {
	public Base() {
		System.out.println("Base() 생성자");
	}
}
class Derived extends Base{
	public Derived() {

		System.out.println("Derived() 생성자");
	}
}
  • 주의사항
    묵시적인 부모 클래스 생성자 호출을 사용하려면 부모 클래스에 기본 생성자(매개 변수가 없는 생성자)가 반드시 정의되어 있어야 함
    class Base{
    	public Base(int x){
    		System.out.println("Base() 생성자");
    }
    
    class Derived extends Base{
    	public Derived() {  
    		System.out.println("Derived() 생성자");
    	}
    }
    
    public class Test{
    	public static void main(String[] args){
    		Derived obj = new Derived();
    	}
    } 
    

Base 클래스에 이미 int형의 인수를 가지는 생성자가 선언되어 있어서 컴파일러가 기본 생성자를 만들지 않았음
이럴 때는 super(100)과 같이 명시적으로 자식 클래스의 생성자 첫 부분에 부모 클래스의 생성자를 호출하는 문장을 넣거나, Base클래스에 기본 생성자를 만들어주면 됨


✔️ 부모 클래스의 생성자 선택

부모 클래스의 생성자가 여러 개 정의되어 있는 경우에, 자식 클래스는 그 중의 하나를 선택할 수 있음

class TwoDimPoint{
	int x, y;

	public TwoDimPoint() {
		x = y = 0;
	}

	public TwoDimPoint(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

class ThreeDimPoint extends TwoDimPoint {
	int z;
	public ThreeDimPoint(int x, int y, int z){
		super(x, y);
		this.z = z;
	}
}

위와 같이 부모 클래스에 2개의 생성자가 정의되어 있는 경우에는 super()와 super(x,y)중에서 하나를 호출할 수 있음


✔️ 메소드 오버라이딩

자식 클래스가 부모 클래스의 메소드를 자신의 필요에 맞추어서 재정의하는 것
이 때 메소드의 이름이나 매개변수, 반환형은 같아야 함

class Shape2{
	public void draw()	{
		System.out.println("Shape");
	}
}
class Rectangle extends Shape2{ 
@Override
	public void draw() {
		System.out.println("Rectangle");
	}
}
class Triangle extends Shape2{
@Override
	public void draw() {
		System.out.println("Triangle");
	}
}
public class ShapeTest {

	public static void main(String[] args) {
		Rectangle s = new Rectangle();
		s.draw();
	}

}

✔️ 메소드 오버로딩

같은 클래스 내에서 메소드의 이름이 같아도 파라미터의 개수나 데이터 형식만 다르면 여러 개를 선언할 수 있는 것


✔️ 정적 메소드 오버라이딩

class Animal{
	public static void A(){
		System.out.println("static method in Animal");
	}
}
public class Dog extends Animal{
	public static void A(){
		System.out.println("static method in Dog");
	}
	public static void main(String[] args){
		Dog dog = new Dog();
		Animal a = dog;
		a.A();
		dog.A();
	}
}  

출력 결과 :
static method in Animal
static method in Dog

Dog참조 변수를 통하여 정적 메소드를 호출하면 자식 클래스의 정적 메소드가 호출되고, Animal 참조 변수를 통하여 정적 메소드를 호출하면 부모 클래스의 정적 메소드가 호출됨

만약 정적 메소드가 아니었다면 a를 통하여 호출했어도 자식 클래스의 A()가 호출되었을 것

✔️ 다형성(polymorphism)

하나의 식별자로 여러 개의 작업을 처리하는 것
똑같은 명령을 내려도 객체의 타입이 다르면 서로 다른 결과를 얻을 수 있는 것

메소드 오버로딩, 메소드 오버라이딩, 제네릭 프로그래밍

하나의 코드로 다양한 타입의 객체를 처리하는 기법

✔️ 업캐스팅

부모 클래스의 변수로 자식 클래스 객체를 참조하는 것

class Shape3 {
	protected int x,y;
	public void draw() {
		System.out.println("Shape Draw");
	}
}
class Rectangle2 extends Shape3{
	private int width, height;
	public void draw() {
		System.out.println("Rectangle Draw");
	}
}

public class ShapeTest2 {

	public static void main(String[] args) {
		Shape3 s1, s2;
		
		s1 = new Shape3();
		s2 = new Rectangle2();	// 가능? ㅇㅇ
		
	}

}

그렇다면 s2를 통하여 자식 클래스의 모든 필드와 메소드를 사용할 수 있을까?

ㄴㄴ

==> 부모클래스로부터 상속받은 부분만을 s2를 통해서 사용할 수 있고 나머지는 사용 불가
s2는 Shape3타입의 변수이기 때문

public class ShapeTest2 {

	public static void main(String[] args) {
		Shape3 s = new Rectangle2();
		Rectangle2 r =  new Rectangle3();	
		// r을 통해서는 모든 필드 Shape3와 Rectangle2의 필드와 메소드 모두 사용 가능 

		s.x =0;	// 슈퍼클래스의 필드와 메소드는 사용 가능
		s.y =0;
		s.width =100; // s를 통해서 Rectangle2 클래스의 필드와 메소드에 접근 불가
		s.height =100;
		
	}
}
  • 활용
    동적 바인딩의 용도
    메소드의 매개변수 선언

    만약 자바에서 생성되는 모든 객체를 전부 전달받을 수 있는 메소드를 선언하고 싶다면 모든 객체는 Object 클래스를 상속 받는다는 것을 기억

public class ShapeTest{
	public static void print(Shape s){	//Shape에서 파생된 모든 클래스의 객체를 다 받을 수 있음
		System.out.println("~~~");
    }
}

✔️ 다운 캐스팅

부모 객체를 자식 참조 변수로 참조하는 것. 명시적으로 사용해야 함

class Parent{
	void print() {
		System.out.println("Parent 메소드 호출");
	}
}
class Child extends Parent {

	@Override
	void print() {
		System.out.println("Child 메소드 호출");
	}
	
}

public class Casting {

	public static void main(String[] args) {
		Parent person = new Child();
		person.print();
		
		Child down = (Child)person;	// 다운캐스팅 : 부모 객체를 자식 객체로 형변환
		down.print();
	}
}

✔️ 동적 바인딩

JVM이 실행 단계에서 변수가 참조하는 객체의 실제 타입을 보고 적절한 메소드를 호출하는 것
오버라이드된 메소드 호출이 컴파일 시간이 아닌 실행 시간에 결정되는 메커니즘
객체의 실제 타입이 호출되는 메소드를 결정하는 것

✔️ 정적 바인딩과 동적 바인딩

자바는 오버로드된 메소드에 대해 정적 바인딩을 사용하고 오버라이드된 메소드에 대해 동적 바인딩을 사용함
즉 오버로드된 메소드는 컴파일할 때 결정되지만, 오버라이드된 메소드는 실행 시간까지 바인딩이 연기되었다가 실행 시간에 실제 타입을 보고 어떤 메소드를 호출할 것인지를 결정한다는 것

✔️ instanceof 연산자

변수가 가리키는 객체의 실제 타입을 알고 싶을 때 사용하는 연산자

if(obj instanceof Rectangle) {...}

위의 코드에서 obj라는 참조변수가 현재 Rectangle 객체를 참조하고 있다면 true를 반환

✔️ 종단 클래스와 종단 메소드

종단 클래스(final class)는 상속시킬 수 없는 클래스를 말함
보안상의 이유로 사용
클래스의 선언 맨 앞에 final을 붙임
재정의 불가

final class String{...}

일반 클래스에서 특정한 메소드만 재정의될 수 없게 만들려면 종단 메소드(final method)를 선언하면 됨

✔️ 구성(composition)

클래스가 다른 클래스의 인스턴스를 클래스의 필드로 가지는 디자인 기법
코드의 재사용성 제공
상속은 한 클래스를 다른 클래스에서 파생시키는 반면 구성은 하나의 클래스를 다른 클래스의 합으로 정의
구성을 통해 생성된 클래스와 객체는 느슨하게 결합되어 코드를 손상시키지 않고 구성 요소를 더 쉽게 변경할 수 있음

✔️ 상속과 구성의 차이

상속구성
is-a 관계has-a 관계
하나의 클래스만 상속, 하나의 클래스에서만 코드 재사용여러 클래스에서 재사용
컴파일 시간에 결정실행 시간에 결정될 수 있음
final로 선언된 클래스의 코드 재사용 불가final로 선언된 클래스에서도 코드 재사용 가능
부모 클래스의 public 및 protected 메소드를 모두 노출아무것도 노출되지 않고, 공개 인터페이스만을 사용하여 상호작용

+) 상속에서는 메소드 오버라이딩 기능을 통해 부모 클래스의 메소드를 수정할 수 있음
상속은 내부 구조를 하위 클래스에 노출한다. 만약 구성을 사용하게 되면 객체는 캡슐화된 상태로 유지
구성은 구현 독립성을 허용

  • is-a 관계
    사과는 과일의 일종이다.
    자동차는 차량의 일종이다. 등 is-a관계가 있다면 상속을 사용

    따라서 상속 사용을 고려할 때는 항상 자식 클래스가 실제로 부모 클래스의 특수한 버전인지 생각해봐야 함

    is-a 관계가 아님에도 무분별하게 상속을 사용하면 단점이 더 많음

  • has-a 관계
    자동차는 엔진을 가지고 있다.
    도서관은 책을 가지고 있따. 등 has-a 관계가 성립되면 이 관계는 상속으로 모델링하면 안됨

    하나의 클래스 안에 다른 클래스의 객체를 포함시키면 됨

    
    class Vehicle()
    class Engine()
    class Brake()
    
    public class Car extends Vehicle{
    		pirvate Engine e;
    	private Brake b;
    	pubic Car()	{
    			this.e = new Engine();
    		this.b = new Brake();
    	}
    }
    

    Vehicle클래스와 Car클래스는 is-a 관계

    Car클래스와 Engine클래스, Brake클래스는 has-a 관계

    has-a관계에서는 하나의 클래스 안에 다른 클래스를 가리키는 참조 변수가 포함되고 여기에 실체 객체가 생성되어서 대입된다

profile
자자 선수입장~

0개의 댓글