📄 학습내용
다형성
- 일반적인 다형성 : 객체를 여러 가지 형태로 변화될 수 있는 성질
- 자바에서 다형성 : 어떤 타입의 참조변수를 통해서 다양한 타입의 객체를 참조할 수 있는 것
- 즉, 상위 클래스 타입의 참조변수가 하위 클래스 객체를 참조할 수 있는 것(역상황은 성립 X)
- 상위 클래스 타입의 참조변수가 하위 클래스 객체를 참조하는 하는 경우
→ 객체가 사용할 수 있는 멤버의 개수 = 참조변수가 사용할 수 있는 멤버의 개수 = 상위 클래스의 멤버의 개수 - 다형성 예시 : 메서드 오버라이딩, 메서드 오버로딩
- 장점 : 중복되는 코드를 줄여서 코드 작성 용이
// 부모 클래스
class Parent {
void print1() {
System.out.println("print1");
}
void print2() {
System.out.println("print2");
}
}
// 자식 클래스
class Child extends Parent {
@Override
void print1() {
System.out.println("child print1");
}
void print3() {
System.out.println("child print3");
}
}
public class Test {
public static void main(String[] args) {
Parent p = new Child(); // 다형성
p.print1(); // Child 클래스에서 오버라이딩한 메서드가 동작
p.print2(); // Parent 클래스 메서드 사용O
// p.print3(); // Child 클래스에만 있는 메서드 사용X
}
}
/* 출력
child print1
print2
*/
- 참조변수의 타입 변환(캐스팅)
- 객체는 참조 변수의 멤버 개수에 따라서 사용할 수 있는 멤버의 개수가 정해짐
- 참조변수의 타입 변환 : 사용가능한 멤버의 개수를 조절하는 행위
- 조건
- 상속관계
- 업캐스팅(하위 클래스 → 상위 클래스 타입 변환) : 형변환 연산자 생략 가능
- 다운캐스팅(상위 클래스 → 하위 클래스 타입 변환) : 형변환 연산자 생략 불가능


- instanceof 연산자
- 캐스팅 가능 여부를 boolean 값으로 반환하는 연산자
- 참조 변수 = null이면 false 반환
참조변수 instanceof 캐스팅할_참조타입
class Parent {} // 상위 클래스
class Child extends Parent {} // 하위 클래스1
class Baby extends Parent {} // 하위 클래스2
public class Test {
public static void main(String[] args) {
Parent parent = new Parent();
System.out.println(parent instanceof Object); // true
System.out.println(parent instanceof Parent); // true
System.out.println(parent instanceof Child); // false, 하위 클래스로 캐스팅 불가능
Parent child = new Child();
System.out.println(child instanceof Object); // true
System.out.println(child instanceof Parent); // true
System.out.println(child instanceof Child); // true
System.out.println(child instanceof Baby); // false, 자손관계에서만 캐스팅 가능
}
}
추상화
- 추상화
- 자바에서의 추상화 : 객체의 공통된 속성과 기능을 추출해서 정의하는 것
- 상향식 방법 : 하위 클래스들의 공통점을 모아서 상위 클래스 정의
- 하향식 방법 : 공통점을 이용해서 상위 클래스 정의 후 하위 클래스 생성
- 추상화 구현의 핵심 역할
- 추상화 클래스(abstract class)
- 인터페이스(interface)
- 추상화 목적
- 클래스 간의 관계를 효과적으로 설정 가능
- 유지 및 보수 용이
- abstract 제어자
- 클래스와 메서드 앞에 붙여서 추상화시키는 키워드
- 추상 메서드(abstract method) : abstract 키워드가 붙은 메서드
- 추상 클래스(abstract class) : 추상 메서드가 하나 이상 가지고 있는 메서드 또는 abstract 키워드가 붙은 클래스
- 추상 메서드 : abstract 키워드가 붙은 메서드
- 메서드 바디가 없고 메서드 시그니처만 있는 메서드 → 미완성 메서드
- 추상 클래스 : 추상 메서드가 하나 이상 가지고 있는 클래스
- 미완성 클래스 → 추상 클래스의 객체 생성 불가능
- 다른 클래스에 추상 클래스를 extends 키워드를 이용해서 상속받게 해서 추상 메서드를 오버라이딩 후 객체 생성 가능
- 특징
- 유연한 대응 : 다른 클래스에 추상 클래스를 상속시켜서 메서드를 유연하게 작성 가능
- 추상화 구현의 핵심적인 역할
- 상속계층도의 상층부에 위치할수록 추상화 정도가 높음
// 추상 클래스 정의
abstract class Abstract_Class {
// 인스턴스 변수
int a = 10;
// 추상 메서드, 메서드 바디는 없고 메서드 시그니처만 있음
abstract void Abstract_Method();
// 인스턴스 메서드
void method() {
// 메서드 바디
}
}
// 추상 클래스 구현
class Class extends Abstract_Class {
void Abstract_Method() {
System.out.println("Abstract_Method");
}
}
public class Test {
public static void main(String[] args) {
Class c = new Class();
c.Abstract_Method();
}
}
// 실행결과
Abstract_Method
- final 키워드
- final 키워드가 붙으면 변경 불가능 및 확장되지 않는 성질을 가짐
- final 키워드가 붙는 위치에 따라서 성질이 달라짐
- final 클래스 : 다른 클래스가 final이 선언된 클래스 상속 불가능
- final 메서드 : 하위 클래스에서 오버라이딩 불가능
- final 변수 : 값 변경이 불가능한 상수
- 인터페이스
- 기본적으로 추상 메서드와 상수로 이루어진 형태
- 구조
- interface 키워드 사용
- 필드
- 상수 : public static final로 정의, public static final 생략 가능(컴파일러가 자동 추가)
- 메서드
- static과 default 메서드 : 메서드 바디를 정의해야함
- 추상 메서드 : public abstract로 정의, public abstract 생략 가능(컴파일러가 자동 추가)
- 구현
- 추상 클래스와 마찬가지로 바로 객체 생성 불가능
- implements 키워드로 다른 클래스에 상속시켜서 모든 추상 메서드를 구현해야 함
→ 인터페이스를 구현한 클래스를 통해서 객체 생성 가능
- 최고 조상 인터페이스 존재 X
- 다중 구현 가능
- 이유 : 상수는 변경 불가능하고 메서드는 정의되지 않았기 때문에 충돌 발생 X
- 클래스의 다중 상속 불가능 이유 : 동일한 필드와 메서드를 가지는 부모 클래스들이 존재하면 충돌 발생
- 장점
- 선언과 구현 분리 → 코드 변경을 최소화해서 개발기간 단축
- 독립적은 프로그래밍을 통해서 코드 수정이 다른 부분에 미치는 영향 최소화
// 인터페이스 정의
interface Interface {
public static final int a1 = 10; // 상수
int a2 = 20; // public static final 자동 추가
public abstract void method1(); // 추상 메서드
void method2(); // public abstract 자동 추가
default void method3() { // default 메서드
System.out.println("method3");
}
static void method4() { // static 메서드
System.out.println("method4");
}
}
// 인터페이스 구현
class Interface_Class implements Interface {
// a2 = 30; // 상수이기 때문에 변경 불가능
// 추상 클래스 오버라이딩
public void method1() {
System.out.println("method1");
}
// 추상 클래스 오버라이딩
public void method2() {
System.out.println("method2");
}
}
public class Test {
public static void main(String[] args) {
Interface_Class IC = new Interface_Class();
IC.method1();
IC.method2();
IC.method3();
// IC.method4(); // 정적 변수는 상속 X
Interface.method4();
System.out.println(IC.a1);
System.out.println(IC.a2);
}
}
// 출력 결과
method1
method2
method3
method4
10
20
- 추상 클래스와 인터페이스 차이
- 추상성 : 추상 클래스 < 인터페이스
- 추상 클래스 정의 : 추상 메서드가 하나 이상 추가된 클래스
- 인터페이스 정의 : 상수, static & default 메서드, 추상 메서드만으로 구성됨
⭐ 공부 난이도
다형성, 추상화 ☆☆☆★★
다형화에서 캐스팅 가능한 경우는?
인터페이스에 static 메서드를 선언한 경우, 이 인터페이스를 상속받은 클래스에서 static 메서드를 상속받는가?
🌕 느낀점
추상화보다는 다형성이 어려웠다 처음에 글을 읽고 실습을 했을 때에는 뭔가 알고 있다고 생각했는데, 심화 학습에서 다양한 코드를 보다가 어느 순간 내가 잘못 알고 있다는 생각이 들어서 시간이 오래 걸렸다. 특히 참조변수의 타입변환에서 왜 이렇게 변환되는지 이해하는 것이 어려웠다. 그리고 추상화의 예제 코드를 만다는 과정에서 에러가 생각보다 많이 발생했고, 왜 에러가 발생했는지를 생각하면서 많이 배웠다. 인터페이스에 static 메서드를 선언하고 이 인터페이스를 상속받은 클래스는 static 메서드를 상속받지 못한다는 사실에 깜짝 놀랬다. 그런데 왜 안되는지 이해가 되지 않았다. 구글링을 해서 찾아봐도 아직까지 이해가 되지 않는다. 이 부분은 내일 다시 확인해보아야 겠다.
'코드스테이츠 - 3회차 백엔드 부트캠프 > Section 1' 카테고리의 다른 글
2022.09.13 화 - 열거형, 제네릭, 예외처리, 컬렉션 (0) | 2022.09.13 |
---|---|
2022.09.08 목 - 프로그램 작성 (0) | 2022.09.08 |
2022.09.06 화 - 상속, 캡슐화 (0) | 2022.09.06 |
2022.09.05 월 - 생성자와 내부 클래스 (0) | 2022.09.05 |
2022.09.02 금 - 클래스와 객체 (0) | 2022.09.02 |