이 챕터에서 중요한 부분은 개인적으로 오버로딩과 다형성, 추상 클래스라고 생각한다.
특히 추상 클래스는 큰 프로젝트의 협업에서 유용하게 쓰이겠다는 생각이 들었다.
이에 대한 정리는 Programming_Knowledge카테고리에 따로 정리할 예정이다.

확인 문제

자바의 상속에 대한 설명 중 틀린 것은?

  1. 자바는 다중 상속을 허용한다.
  2. 부모의 메소드를 자식 클래스에서 재정의(오버라이딩)할 수 있다.
  3. 부모의 private 접근 제한을 갖는 필드와 메소드는 상속의 대상이 아니다.
  4. final 클래스는 상속할 수 없고, final 메소드는 오버라이딩 할 수 없다.

자바는 다른 언어와 달리 다중 상속을 허용하지 않는다.

클래스 타입 변환에 대한 설명 중 틀린 것은?

  1. 자식 객체는 부모 타입으로 자동 타입 변환된다.
  2. 부모 객체는 항상 자식 타입으로 강제 타입 변환된다.
  3. 자동 타입 변환을 이용해서 필드와 매개 변수의 다형성을 구현한다.
  4. 강제 타입 변환 전에 instanceof 연산자로 변환 가능한지 검사하는 것이 좋다.

부모 객체가 자식 타입으로 선언 된 뒤, 자식 타입으로 강제 타입 변환 할 경우에만 타입 변환이 가능하다.

final 키워드에 대한 설명으로 틀린 것은?

  1. final 클래스는 부모 클래스로 사용할 수 있다.
  2. final 필드는 값이 저장된 후에는 변경할 수 없다.
  3. final 메소드는 재정의(오버라이딩)할 수 없다.
  4. static final 필드는 상수를 말한다.

final 클래스는 상속이 불가능하다.

오버라이딩(Overriding)에 대한 설명으로 틀린 것은?

  1. 부모 메소드의 시그너처(리턴 타입, 메소드명, 매개 변수)와 동일해야 한다.
  2. 부모 메소드보다 좁은 접근 제한자를 붙일 수 없다.(ex. public > private)
  3. @Override 어노테이션을 사용하면 재정의가 확실한지 컴파일러가 검증한다.
  4. protected 접근 제한을 갖는 메소드는 다른 패키지의 자식 클래스에서 재정의할 수 없다.

protected 접근 제한은 다른 패키지일 경우 자식 클래스에서만 사용할 수 있다.
4번 내용은 default 접근 제한을 갖는 메소드로 볼 수 있다.

Parent 클래스를 상속한 Child 클래스의 생성자에서 컴파일 에러가 발생한 이유는?

public class Parent{
	public String name;

	public Parent(String name){
		this.name = name;
	}
}

public class Child extends Parent{
	private int studentNo;

	public Child(String name, int studentNo){
		this.name = name;
		this.studentNo = studentNo;
	}
}

부모 클래스의 생성자가 명시적 생성자일 경우, 컴파일러가 자식 클래스 인스턴스 생성 시 자동으로 부모 클래스를 생성할 수 없다.
따라서 자식 클래스에서는 부모 클래스의 생성자를 명시해줘야 하므로 위 코드는 아래와 같이 바뀌어야 한다.

public class Child extends Parent{
	private int studentNo;

	public Child(String name, int studentNo){
		super(name);
		this.studentNo = studentNo;
	}
}

Parent 클래스를 상속받은 Child 클래스가 있을 때, ChildExcample 클래스의 출력 결과는?

public class Parent{
	public String nation;

	public Parent(){
		this("대한민국");
		System.out.println("Parent() call");
	}

	public Parent(String nation){
		this.nation = nation;
		System.out.println("Parent(String nation) call");
	}
}

public class Child extends Parent{
	private String name;

	public Child(){
		this("홍길동");
		System.out.println("Child() call");
	}

	public Child(String name){
		this.name = name;
		System.out.println("Child(String name) call");
	}
}

public class ChildExample{
	public static void main(String[] args){
		Child child = new Child();
	}
}
출력결과
Parent(String nation) call
Parent() call
Child(String name) call
Child() call

여기서 this()는 현재 클래스의 생성자를 의미한다!

Tire 클래스를 상속받아 SnowTire 클래스를 작성했을 때, SnowTireExample 클래스의 출력 결과는?

public class Tire{
	public void run(){
		System.out.println("일반 타이어가 굴러갑니다.");
	}
}

public class SnowTire extends Tire{
	@Override
	public void run(){
		System.out.println("스노우 타이어가 굴러갑니다.");
	}
}

public class SnowTireExample{
	public static void main(String[] args){
		SnowTire snowTire = new SnowTire();
		Tire tire = snowTire;

		snowTire.run();
		tire.run();
	}
}
출력결과
스노우 타이어가 굴러갑니다.
스노우 타이어가 굴러갑니다.

tire변수를 snowTire객체로 생성했으므로, 오버라이딩 된 snowTire의 메소드가 실행된다.

A, B, C, D, E, F 클래스가 상속 관계에 있을 때 다음 빈칸에 들어올 수 없는 코드는?

부모 클래스 자식 클래스
A B C
B D E
C F
public class A{ ... }
public class B extends A{ ... }
public class C extends A{ ... }
public class D extends B{ ... }
public class E extends B{ ... }
public class F extends C{ ... }
B b = _____;

메소드 선언: void method(B b){ ... }
메소드 호출: method( ________ )
  1. new B()
  2. (B) new A() //강제 타입 변환
  3. new D() //자동 타입 변환
  4. new E() //자동 타입 변환

부모 클래스가 자식 클래스로 타입 변환이 가능해지기 위해서는, 이전에 부모 클래스가 자식 클래스로 타입 변환이 된 적이 있어야한다.
하지만 이 경우 new A()로 완전히 새로운 객체를 참조하도록 하기 때문에 강제 타입이 불가능하다.
만약 2번과 같은 경우가 가능해지려면, 아래와 같이 선언되어야 한다.

A a = new B();
B b = (B) a;