1. Class Promotion, Class Casting
💡 Class Promotion이란? (형식 승격)
일반적으로 더 넓은 범위나 더 상위의 타입으로 객체를 자동으로 변환하는 것을 의미한다.
이는 주로 상속 구조에서 발생한다. 예를 들면 서브클래스의 객체가 슈퍼클래스 타입의 변수에 할당될 때
자동으로 승격된다. 이 과정은 컴파일러에 의해 자동으로 처리되며, 명시적인 캐스팅을 필요로 하지 않는다.
💻 예시 코드
class Animal {}
class Dog extends Animal {}
public class Test {
public static void main(String[] args) {
Dog myDog = new Dog();
Animal myAnimal = myDog; // 강아지가 자동으로 동물로 승격된다.
}
}
💡 Class Casting이란?
객체의 타입을 명시적으로 변환할 때 사용된다. 이는 주로 더 구체적인 타입으로 객체를 캐스팅할 때 필요하며, 개발자가 명시적으로 형 변환을 선언해야 한다. 이런 형태의 캐스팅은 실행 시 타입 체크가 이루어지기 때문에, 잘못된 캐스팅은 ClassCastExeption을 발생시킬 수 있다.
💻 예시 코드
class Animal {}
class Dog extends Animal {}
public class Test {
public static void main(String[] args) {
Animal myAnimal = new Dog();
Dog myDog = (Dog) myAnimal; // 동물에서 개로 명시적 캐스팅.
}
}
📌 차이점
- 자동성 여부
Promotion은 자동적으로 이루어지지만, Casting은 명시적으로 지정해야 한다. - 방향성
Promotion은 보통 하위 클래스에서 상위 클래스로의 변환이며, Casting은 상위 클래스에서
하위 클래스의 변환을 포함할 수 있다. - 안정성
Promotion은 안전하다고 간주되지만, Casting은 잘못 사용할 경우 런타임 에러를 일으킬 수 있다.
💻 예제 코드
package pack03;
public class Ex15_PolyTaxi extends Ex15_PolyCar {
private int passenger = 2;
public Ex15_PolyTaxi() {
// super();
System.out.println("난 택시라고 해");
}
@Override
public void displaySpeed() {
System.out.println("택시 승객은 " + passenger + "명");
}
}
package pack03;
// 자동차가 가져아 할 기본 멤버를 선언한 자원 클래스
// 다른 클래스 포함 또는 상속을 통해 자원을 사용할 수 있다.
public class Ex15_PolyCar {
protected int speed = 50;
public Ex15_PolyCar() {
System.out.println("나는 자동차 원형 클래스댱");
}
public void displaySpeed() {
System.out.println("속도 : " + speed );
}
public int getSpeed() {
return speed;
}
}
package pack03;
public class Ex15_PolyBus extends Ex15_PolyCar {
private int passenger = 10;
public void show() { // Ex15_PolyBus 고유 메소드
System.out.println("버스");
}
@Override // Annotation, 메타데이터 : 컴파일러에게 다양한 정보를 알려주는 역할
public void displaySpeed() {
System.out.println("버스 승객 수는 " + passenger);
System.out.println("버스의 속도는 " + speed);
}
}
package pack03;
public class Ex15_PolyMain {
public static void main(String[] args) {
Ex15_PolyCar car1 = new Ex15_PolyCar(); // 부모
Ex15_PolyBus bus1 = new Ex15_PolyBus(); // 자식
Ex15_PolyTaxi taxi1 = new Ex15_PolyTaxi(); // 자식2
System.out.println();
car1.displaySpeed();
System.out.println(car1.getSpeed());
System.out.println();
bus1.displaySpeed();
System.out.println(bus1.getSpeed());
bus1.show();
System.out.println();
taxi1.displaySpeed();
System.out.println(taxi1.getSpeed());
System.out.println("----- 객체 주소 치환 -----");
Ex15_PolyCar car2 = new Ex15_PolyBus(); // promotion
car2.displaySpeed(); // 오버라이딩된 메소드(호출 가능)
System.out.println(car2.getSpeed()); // car2.getSpeed()도 버스 값(50)을 찾다가 없으면 부모(car1)의 값을 찾으러 떠남
// car2.show(); (오버라이딩x) // 자식 고유의 메소드는 간섭(호출) 불가
// = 오버라이딩된 메소드만 호출할 수 있다. 오버라이드하지 않은 고유 메소드는 호출할 수 없다.
Ex15_PolyCar car3 = taxi1; // promotion // Polycar는 taxi1의 값을 가지게 된다.
System.out.println("주소 확인 :" + car3 + " " + taxi1);
car3.displaySpeed();
System.out.println(car3.getSpeed());
System.out.println("\n\n==========================\n\n");
// Ex15_PolyBus bus2 = new Ex15_PolyCar(); //안됨!!
// Ex15_PolyBus bus3 = car2; // 실질적으로 car2가 갖고 있는 값은 polybus임.. (Type mismatch) .. 근데 강제로 바꿀 수 있음!
Ex15_PolyBus bus3 = (Ex15_PolyBus)car2; // Casting으로 성립시킬 수 있당~!!
// // car2는 부모타입이지만 bus(자식)의 주소를 갖고 있으므로 casting에 의해 치환이 가능하다~!
bus3.displaySpeed();
System.out.println();
// Ex15_PolyTaxi taxi2 = new Ex15_PolyCar(); // 성립 안됨
// Ex15_PolyTaxi taxi2 = new car3; // (부모)polycar타입이라 type mismatch
Ex15_PolyTaxi taxi2 = (Ex15_PolyTaxi)car3; // casting으로 성립
taxi2.displaySpeed();
// Ex15_PolyTaxi taxi3 = (Ex15_PolyTaxi)car1; // ClassCastException(Runtime error)
System.out.println("\n\n^^^^이것이 다형성^^^^^\n\n");
// 오버라이딩된 메소드를 출력함으로써 메소드는 같지만 각자의 주소를 참조해서 다른 결과가 나온다.
Ex15_PolyCar mycar;
mycar = bus1;
mycar.displaySpeed();
mycar = taxi1;
mycar.displaySpeed();
System.out.println("\n\n\n----- PolyCar 타입의 배열 선언 -----");
Ex15_PolyCar p[] = new Ex15_PolyCar[3];
p[0] = car1;
p[1] = bus1;
p[2] = taxi1;
// 향상된 for문을 통해 p를 출력
for(Ex15_PolyCar poly:p) {
poly.displaySpeed();
}
}
}
[Java] Promotion and Casting | 타입 변환
Promotion and Casting 타입 변환 - Java는 Type에 엄격한 언어이며, 타입간의 묵시적·명시적 변환을 허용한다. Promotion (프로모션; 자동 타입 변환) - 묵시적으로, 자동으로 타입을 변환하는 것을 의미한
dad-rock.tistory.com
- 출처 : dad-rock tistory
2. 추상 클래스 (Abstract Class)
다른 클래스가 상속받을 수 있는 기반 클래스이다. 하지만 추상 클래스 자체로는 인스턴스를 생성할 수 없다.
추상 클래스는 하나 이상의 추상 메소드를 포함할 수 있으며, 일반 메소드도 포함할 수 있다. 이 클래스는
상속받는 서브클래스가 특정 메소드를 구현하도록 강제하는 데 사용된다.
💻 예시 코드
abstract class Animal {
abstract void eat(); // 추상 메소드
void breathe() { // 일반 메소드
System.out.println("Breathing");
}
}
3. 추상 메소드 (Abstract Method)
선언만 있고 구현이 없는 메소드이다. 추상 메소드는 추상 클래스 내부에 선언되며, 이 메소드를 포함하는 클래스가 추상 클래스임을 의미한다. 서브클래스는 반드시 이 추상 메소드를 구현해야 한다. 이는 서브클래스가 특정 작업을 수행하는
방식에 대한 유연성을 제공하며, 다형성을 활용할 수 있게 한다.
💻 예시 코드
class Dog extends Animal {
@Override
void eat() {
System.out.println("Dog is eating");
}
}
💻 예제 코드
package pack03;
abstract class Ex18_Animal { // 추상 클래스
abstract public String name(); // 추상 메소드
abstract public String eat();
abstract public String action();
public void animalPrint() { // 일반 메소드
System.out.println("동물 추상 클래스의 일반 메소드");
}
}
package pack03;
public class Ex18_Cow extends Ex18_Animal{
@Override
public String name() {
return "내 이름은 소야";
}
@Override
public String eat() {
return "여물";
}
@Override
public String action() {
return "낮에 활동";
}
}
package pack03;
public class Ex18_Lion extends Ex18_Animal{
@Override
public String name() {
return "내 이름은 사자야. 어흥";
}
@Override
public String eat() {
String gogi = "생고기";
return gogi;
}
@Override
public String action() {
return "밤에 움직임";
}
public void eatOther() {
System.out.println("가끔 물도 마심");
}
}
package pack03;
public class Ex18_Main {
public static void main(String[] args) {
Ex18_Cow cow = new Ex18_Cow();
System.out.println(cow.name());
System.out.println(cow.action());
System.out.println(cow.eat());
cow.animalPrint();
System.out.println();
Ex18_Lion lion = new Ex18_Lion();
System.out.println(lion.name());
System.out.println(lion.action());
System.out.println(lion.eat());
lion.animalPrint();
lion.eatOther(); // 사자 고유 메소드
System.out.println();
Ex18_Animal animal = null;
animal = cow;
System.out.println(animal.name());
animal = lion;
System.out.println(animal.name());
System.out.println("\n별도의 클래스 사용해보기\n");
Ex18_FindUtil.find(cow);
System.out.println();
Ex18_FindUtil.find(lion);
}
}
💻 결과
내 이름은 소야
낮에 활동
여물
동물 추상 클래스의 일반 메소드
내 이름은 사자야. 어흥
밤에 움직임
생고기
동물 추상 클래스의 일반 메소드
가끔 물도 마심
내 이름은 소야
내 이름은 사자야. 어흥
4. FindUtil (주소비교)
💻 예제 코드
package pack03;
public class Ex18_FindUtil {
public static void find(Ex18_Animal ani) {
ani.animalPrint();
// instanceof : 객체 타입 비교 연산
if(ani instanceof Ex18_Cow) {
Ex18_Animal a = ani;
System.out.println(a.name());
System.out.println(a.eat());
}else if (ani instanceof Ex18_Lion) {
System.out.println(ani.name());
System.out.println(ani.eat());
((Ex18_Lion) ani).eatOther();
}
}
}
💻 결과
내 이름은 소야
낮에 활동
여물
동물 추상 클래스의 일반 메소드
내 이름은 사자야. 어흥
밤에 움직임
생고기
동물 추상 클래스의 일반 메소드
가끔 물도 마심
내 이름은 소야
내 이름은 사자야. 어흥
별도의 클래스 사용해보기
동물 추상 클래스의 일반 메소드
내 이름은 소야
여물
동물 추상 클래스의 일반 메소드
내 이름은 사자야. 어흥
생고기
가끔 물도 마심
오후에는 추상클래스에 대해 연습문제를 풀어보는 시간을 가졌다.
선생님이 제시하신 다이어그램을 참고하여 문제를 풀었다.
이전의 문제들도 어려웠었지만, 오늘은 특히나 더욱 어려웠었다.
접근제한자의 표시(+, -)들의 뜻은 알아서 속성 선언하는 것까지는 문제가 없었는데 이후에 생성자와 오버라이딩을 어떻게, 몇 번째 줄에 코드를 작성해야 하는지 까마득해서 수업한 내용을 토대로 보면서 적어보았다.
점심시간 끝나고서부터 학원 끝날 때까지 계속 문제만 풀었다.
옆에 앉은 동생이 도와줘서 나머지 못 한 부분을 잘 마무리했다. 수업 마치기 1시간 전에 선생님이 이 코드에 대한 설명을 해보라고 시키셨었는데, 나는 코드가 늦게 마무리돼서 오늘은 하지 못하고 다음날 하기로 했다.
이것저것 헷갈려하는 나에게는 좋은 기회다라고 생각하고 열심히 공부해야겠다.
'에이콘아카데미 회고 > 5회차) 자바기반 풀스택 개발자 양성과정' 카테고리의 다른 글
JAVA) 11번째 회고 (0) | 2024.04.15 |
---|---|
JAVA) 10번째 회고 (0) | 2024.04.13 |
JAVA) 08번째 회고 (0) | 2024.04.09 |
JAVA) 07번째 회고 (0) | 2024.04.09 |
JAVA) 06번째 회고 (0) | 2024.04.09 |