private List<Room> rooms = new ArrayList<>();
private List<Reservation> reservations = new ArrayList<>();
팀 과제 도중 다른 팀원이 작성한 코드 중 위 코드를 보고 질문했습니다.
ArrayList로 생성하고 List 타입으로 받은 이유가 뭐에요..???
A : 얘가 얘한테 상속.. 다형성이잖아요.
다형성인건 알지만 결국엔 그것은 그걸 표현하는 개념의 이름일 뿐이다.
교재의 예제에서도 종종 저렇게 표현하던데, 그랬을 때의 특징과 장점이 있지 않을까 궁금해졌다.
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
우선 ArrayList를 자바 내 접근해보면 하나의 클래스임을 알 수 있고, List는 implements된 인터페이스임을 확인했다.
ArrayList -> 클래스 / List -> 인터페이스
그렇다면, 아래 두 코드의 차이점은 무엇일까?
private List<Room> rooms = new ArrayList<>(); // List 타입
private ArrayList<Room> rooms = new ArrayList<>(); // ArrayList 타입
결론적으로는 같다고 한다.
하지만 기능적으로 List의 기능을 쓸 경우를 위해, LinkedList의 장점도 가져가기 위해, List를 ArrayList로 구현하고 List로 선언한 것.
private List<Room> rooms = new ArrayList<>(); // List 타입으로 선언하고, ArrayList로 생성해둠.
private List<Room> rooms = new LinkedList<>(); // 이후 LinkedList로 구현체가 바뀌어도 호환.
private ArrayList<Room> rooms = new ArrayList<>(); // ArrayList로 생성됨.
private List<Room> rooms = new LinkedList<>(); // 오류.
이후에 이런식으로 LinkedList로 전환하여 이용이 가능하고, 이 때 LinkedList의 장점인 빠른 추가, 수정, 삭제를 기대해볼 수 있다고 한다.
어떻게 활용할 지는 아직 감이 안 오긴한다.
추가적으로, 의도적으로 해당 클래스보다 부모클래스의 타입 혹은 그 반대의 경우로 타입을 해석하는 경우가 있는데,
이를 '업캐스팅', '다운캐스팅'이라고 한다더라.
업캐스팅, 다운캐스팅이란?
캐스팅이란 단어는 한글로 타입변환(형 변환, Casting)이고 앞서서 기본형 타입을 형변환을 배웠었다.
int i = 10;
double j = (double) i; // j = 10.0
거기서 확장되어, 참조형 타입에서도 형변환이 가능한데, 이를 참조형 캐스팅 (업캐스팅 / 다운캐스팅)이라고 부른다.
class Parent {
String name;
int age;
}
class Child extends Parent {
//String name; // 상속받은 멤버1
//int age; // 상속받은 멤버2
int grade; // 자식클래스만 가지고있는 멤버
}
Parent p = new Parent();
Child c = new Child();
Parent p2 = new Child(); // 업캐스팅 - 기능적으로는 더 좁아진다. grade멤버 사용 불가.
Child c2 = (Child)p2; // 다운캐스팅 - p2는 Child를 참조하기 때문에 명시적으로 형변환이 가능하다.
업/다운캐스팅의 개념 자체는 위에 기술한 대로다.
중요한 건 각 특징과 어떤 쓰임을 갖는 지 같다.
업캐스팅의 특징
- 업캐스팅은 캐스팅 연산자 괄호를 생략할 수 있다. (ex. Parent p2 = new Child();)
- 단, 부모 클래스로 캐스팅 된다는 것은 멤버의 갯수 감소를 의미한다. (부모 클래스 멤버만 접근 가능)
- 업캐스팅을 하고 메소드를 실행할때, 만일 자식 클래스에서 오버라이딩한 메서드가 있을 경우, 부모 클래스의 메서드가 아닌 오버라이딩 된 메서드가 실행되게 된다.
업캐스팅 하는 이유
: '공통적으로 할 수 있는 부분을 만들어 간단하게 다루기 위함.'으로 정리되어 있다.
아래 feature와 size를 멤버로 갖고, bark라는 메소드를 갖는 Animal 클래스를 만들었다.
그리고 이를 상속받아 각 Dog, Cat, Goat 클래스를 만든 뒤 bark()메소드를 오버라이딩 했다.
class Animal {
String feature;
int size;
void bark(){
System.out.println("짖다!");
}
}
class Dog extends Animal {
@Override
void bark(){
System.out.println("짖다!");
}
}
class Cat extends Animal {
@Override
void bark(){
System.out.println("이야오옹~");
}
}
class Goat extends Animal {
@Override
void bark(){
System.out.println("곹.곹.");
}
}
이렇게 되면 부모 자식 클래스가 형성되고 각 동물클래스를 부모클래스인 Animal클래스로 업스캐스팅이 가능하다.
Animal dog = new Dog();
Animal cat = new Cat();
Animal goat = new Goat();
Animal[] zoo = {dog, cat, goat};
이처럼 Animal 타입으로 선언 후 각 자식클래스로 생성이 가능했고,
zoo라는 Animal타입의 배열에 삽입해도 문제없다.
마지막으로 다형성의 꽃으로다가 다음 반복문을 실행해보자.
bark()하나로 각각의 결과를 얻을 수 있다니. 도파민이 분출된다.
다운캐스팅
다운캐스팅은 간략하게 설명해보자면,
'부모 클래스로 업 캐스팅된 자식 클래스를 복구하여, 본인의 필드와 기능을 회복하는 기능'
업캐스팅시에 사용할 수 없게된 멤버를 다시 되찾고 싶을 때 사용할 수 있는 것이다.
자연스럽게, 업캐스팅 된 객체만 가능하고 그렇지않으면 오류가 발생한다.
Animal fakeDog = new Animal();
Dog realDog = (Dog) fakeDog; //fakeDog는 Animal을 참조하는 객체라 다운캐스팅이 불가능하다.
System.out.println(realDog.size);
///오류메시지///
Exception in thread "main" java.lang.ClassCastException: class Animal cannot be cast to class Dog (Animal and Dog are in unnamed module of loader 'app')
at Upcasting.main(Upcasting.java:11)
'Back-End > Java' 카테고리의 다른 글
TIL 230612 : 날짜 시간 데이터와 인사하기. (2. SimpleDateFormat) (0) | 2023.06.12 |
---|---|
TIL 230609 : 날짜 시간 데이터와 인사하기. (1. Calendar, Date) (0) | 2023.06.09 |
TIL 230605 : Stringbuilder랑 가까워지기. (0) | 2023.06.06 |
TIL 230602 : 튜터님의 코드와 비교해보는 코드리뷰 (키오스크 주문 프로그램) (0) | 2023.06.04 |
TIL 230601 : ArrayList와 함께한 오늘의 삽질들. (0) | 2023.06.01 |