chap05_1 - Phone.class, SmartPhone.class, PhoneEx.class
Phone.class
public abstract class Phone { // abstract 추가 : 추상 클래스
public String owner;
public Phone(String owner) {
this.owner = owner;
}
public void turnOn() {
System.out.println("휴대폰 전원을 켭니다.");
}
public void turnOff() {
System.out.println("휴대폰 전원을 끕니다.");
}
}
SmartPhone.class
public class SmartPhone extends Phone{ // Phone 클래스를 상속받아 사용
public SmartPhone(String owner) {
super(owner); // 부모클래스 Phone에 owner 대입 -> 본인의 멤버변수 owner로 저장
}
public void internetSearch() {
System.out.println("인터넷 검색을 합니다.");
}
}
PhoneEx.class
public class PhoneEx {
public static void main(String[] args) {
SmartPhone smartPhone = new SmartPhone("홍길동");
smartPhone.turnOn();
smartPhone.internetSearch();
smartPhone.turnOff();
// Phone 클래스는 추상 클래스 이므로 new 키워드를 통해 (직접적인)객체를 생성할 수 없음
// Phone phone = new Phone("홍길동"); // 에러 발생
Phone phone; // 해당 클래스 타입의 변수 만드는건 가능 , new 를 못씀
}
}
chap05-1 - Aminal.class, Dog.class, Cat.class, AnimalEx.class
Aminal.class
public abstract class Animal {
public String kind;
public Animal(String kind) {
this.kind = kind;
}
public void breathe() {
System.out.println(this.kind + "가 숨을 쉽니다.");
}
public abstract void sound();
}
Dog.class
public class Dog extends Animal{
public Dog(String kind) {
super(kind);
}
@Override
public void sound() {
System.out.println(kind + "는 멍멍");
}
}
Cat.class
public class Cat extends Animal{
public Cat(String kind) {
super(kind);
}
@Override
public void sound() {
System.out.println(kind + "는 냐옹");
}
}
AnimalEx.class
public class AnimalEx {
public static void animalSound(Animal animal) {
animal.sound();
}
public static void main(String[] args) {
Dog dog = new Dog("멍멍이");
Cat cat = new Cat("고양이");
dog.breathe();
dog.sound();
cat.breathe();
cat.sound();
System.out.println("--------------------");
// animal = new Animal(); <-- 오류발생: 추상클래스는 상속받아서만 사용 가능, 객체 생성 불가능
// 추상 클래스 타입의 변수를 선언하는 것은 문제가 없음.
Animal animal;
// 클래스의 형변환(다형성)
animal = new Dog("멍멍이");
animal.sound(); // 결과 : 멍멍
animal = new Cat("고양이");
animal.sound(); // 결과 : 냐옹
animalSound(new Dog("강아지")); // 결과 : 강아지는 멍멍
animalSound(new Cat("냐옹이")); // 결과 : 냐옹이는 냐옹
}
}
Animal animal = new Dog();
study05_1 - Parent.class, Child.class, ChildEx.class
Parent.class
public class Parent {
public void method1() {
System.out.println("Parent-method1");
}
public void method2() {
System.out.println("Parent-method2");
}
}
Child.class
public class Child extends Parent{
@Override
public void method2() {
System.out.println("Child-method2()");
}
public void method3() {
System.out.println("Child-method3()");
}
}
ChildEx.class
public class ChildEx {
public static void main(String[] args) {
Parent parent = new Parent(); // 부모 클래스 객체 생성
parent.method1(); // 결과 : Parent-method1
parent.method2(); // 결과 : Parent-method2
System.out.println("--------------");
// Parent 상속받은 Child
// 객체 생성. Child()에는 method1이 없음, method2는 오버라이드 되어있음
Child child = new Child();
child.method1(); // 결과 : Parent-method1 (상속받은 메소드)
child.method2(); // 결과 : Child-method2()
child.method3(); // 결과 : Child-method3()
System.out.println("--------------");
// 다형성 : 부모 클래스 타입의 변수에 자식 클래스 타입의 객체를 대입하여 부모 클래스 타입의 객체인 것처럼 사용하는것,
// 실제 결과물은 자식 클래스 타입의 객체가 가지고 있는 데이터로 출력이 되는것.
parent = child; // parent 클래스 타입(부모)에 child 객체(자식) 대입 - 문제없음
parent.method1(); // 결과 : Parent-method1
parent.method2(); // 결과 : Child-method2() <-- WHY? 껍데기는 부모처럼 생겼지만 알맹이는 Child객체이기때문.
// parent.method3(); : 실행이 안됨 <-- WHY? 알맹이는 Child인데 왜 안되는가?
// 일단은 부모클래스 타입으로 로드가 되었기때문에 자식클래스에서 전용으로 있던것은 숨겨짐.
// 원래 부모님이 하셨던 행동만 사용 가능
// (= 부모 클래스에 없던 메소드<자식클래스에만 있던 메소드>는 사용 불가능)
// 부모 클래스 타입의 변수에 자식 클래스 타입의 갹체를 대입했을 경우
// 자동 형변환이 발생하여 자식 클래스 타입의 객체가 전용으로 가지고 있던 멤버를 활용할 수 없음.
// 부모 클래스 멤버만 사용할 수 있음.
}
}
study05_1 - Tire.class, Car2.class, HankookTire.class, KumhoTire.class, Car2Ex.class, Car3.class
Tire.class
public class Tire {
public int maxRotation; // 최대 회전수
public int accumulatedRotation; // 누적 회전수
public String location; // 타이어 위치
public Tire(String location, int maxRotation) {
this.location = location;
this.maxRotation = maxRotation;
}
public boolean roll() {
++ accumulatedRotation;
if (accumulatedRotation < maxRotation) {
System.out.println(location + "Tire 수명 : " + (maxRotation - accumulatedRotation) + "회");
return true;
}
else {
System.out.println("*** " + location + " Tire 펑크 ***");
return false;
}
}
}
Car2.class
public class Car2 {
Tire frontLeftTire = new Tire("앞왼쪽", 6);
Tire frontRightTire = new Tire("앞오른쪽", 2);
Tire backLeftTire = new Tire("뒤왼쪽", 3);
Tire backRightTire = new Tire("뒤오른쪽", 4);
int run() {
System.out.println("[자동차가 달립니다.]");
if (frontLeftTire.roll() == false) {
stop();
return 1;
}
if (frontRightTire.roll() == false) {
stop();
return 2;
}
if (backLeftTire.roll() == false) {
stop();
return 3;
}
if (backRightTire.roll() == false) {
stop();
return 4;
}
return 0;
}
void stop() {
System.out.println("[자동차가 멈춥니다.]");
}
}
HankookTire.class
public class HankookTire extends Tire{
public HankookTire(String location, int maxRotation) {
super(location, maxRotation);
}
@Override
public boolean roll() {
++accumulatedRotation;
if (accumulatedRotation < maxRotation) {
System.out.println(location + "HankookTire 수명 : " + (maxRotation - accumulatedRotation) + "회");
return true;
}
else {
System.out.println("*** " + location + " HankookTire 펑크 ***");
return false;
}
}
}
KumhoTire.class
public class KumhoTire extends Tire {
public KumhoTire(String location, int maxRotation) {
super(location, maxRotation);
}
@Override
public boolean roll() {
++accumulatedRotation;
if (accumulatedRotation < maxRotation) {
System.out.println(location + "KumhoTire 수명 : " + (maxRotation - accumulatedRotation) + "회");
return true;
} else {
System.out.println("*** " + location + " KumhoTire 펑크 ***");
return false;
}
}
}
Car2Ex.class
import package2.C;
public class Car2Ex {
public static void main(String[] args) {
Car2 car = new Car2();
for(int i=1; i<=5; i++) {
int problemLocation = car.run();
switch (problemLocation) {
case 1:
System.out.println("앞왼쪽 HankookTire로 교체");
// 다형성 활용 (부모 클래스 타입에 자식 클래스 대입)
car.frontLeftTire = new HankookTire("앞왼쪽", 15);
break;
case 2:
System.out.println("앞오른쪽 KumhoTire로 교체");
// 다형성 활용 (부모 클래스 타입에 자식 클래스 대입)
car.frontRightTire = new KumhoTire("앞오른쪽", 13);
break;
case 3:
System.out.println("뒤왼쪽 HankookTire로 교체");
// 다형성 활용 (부모 클래스 타입에 자식 클래스 대입)
car.backLeftTire = new HankookTire("뒤왼쪽", 14);
break;
case 4:
System.out.println("뒤오른쪽 KumhoTire로 교체");
// 다형성 활용 (부모 클래스 타입에 자식 클래스 대입)
car.backRightTire = new KumhoTire("뒤오른쪽", 17);
break;
}
System.out.println("---------------------------------------");
}
// 다형성 이용한 Car3 이용
System.out.println("\n\n");
Car3 car3 = new Car3();
for(int i = 1; i <= 5; i++) {
int problemLocation = car3.run();
if (problemLocation != 0) {
System.out.println(car3.tires[problemLocation -1].location + "HankookTire로 교체");
car3.tires[problemLocation -1] = new HankookTire((car3.tires[problemLocation -1].location), 15);
}
System.out.println("------------------------------------");
}
}
}
Vehicle, Bus, Driver, Taxi, DriverEx 클래스
Vehicle.class
public class Vehicle {
public void run() {
System.out.println("차량이 달립니다.");
}
}
Bus.class
public class Bus extends Vehicle {
@Override
public void run() {
System.out.println("버스가 달립니다.");
}
}
Taxi.class
public class Taxi extends Vehicle {
@Override
public void run() {
System.out.println("택시가 달립니다.");
}
}
Driver.class
public class Driver {
public void drive(Vehicle vehicle) {
vehicle.run();
}
}
DriverEx.class
public class DriverEx {
public static void main(String[] args) {
Driver driver = new Driver();
Bus bus = new Bus();
Taxi taxi = new Taxi();
Vehicle vehicle = new Vehicle();
// 각각의 객체로 실행하는 방식
vehicle.run();
bus.run();
taxi.run();
// 다형성을 이용하여 부모 클래스 타입의 변수에 자식 클래스 타입의 객체를 대입
vehicle = bus; // 다형성
vehicle.run();
vehicle = taxi;
vehicle.run();
// 다른 클래스의 멤버 메서드의 매개변수로 부모클래스 타입의 변수를 사용 시,
// 자식 클래스 타입의 객체를 매개변수로 넘겨서 사용할 수 있음.
// 사용하는 방법은 동일한데, 사용된 데이터에 따라서 다른 출력을 하고 있음
driver.drive(bus);
driver.drive(taxi);
}
}
부모 타입이면 모두 자식 타입으로 강제 타입 변환할 수 있는 것 아님
먼저 자식 타입인지 확인 후 강제 타입 실행해야 함
Parent2.class
public class Parent2 {
public String field1;
public void method1() {
System.out.println("부모 메서드1 실행");
}
public void method2() {
System.out.println("부모 메서드2 실행");
}
}
Child2.class
public class Child2 extends Parent2 {
public String field2;
public void method3() {
System.out.println("자식 메서드3 실행");
}
}
Child2Ex.class
public class Child2Ex {
public static void main(String[] args) {
// 자동 타입 변환
// 부모 클래스 타입의 변수에 자식 클래스 타입의 객체를 대입하면 부모 클래스 타입의 멤버만 사용이 가능함(알맹이는 자식 클래스 타입의 객체)
// 부모흉내를 내고있어서 본인 전용 메소드 사용 못함
Parent2 parent2 = new Child2();
parent2.field1 = "data1";
parent2.method1();
parent2.method2();
//에러 parent2.field2 = "데이터 2";
//에러 parent2.method3();
System.out.println("\n----- 자식 클래스 타입의 변수에 자식 클래스 타입의 객체 대입 -----\n");
// 자식 클래스 타입의 변수에 자식 클래스 객체를 대입하면 부모클래스에서 상속받은것 + 자식 전용 필드 모두 사용 가능
Child2 child2 = new Child2();
child2.field1 = "데이터 1";
child2.field2 = "데이터 2";
child2.method1();
child2.method2();
child2.method3();
System.out.println("\n----- 다시 자식 클래스 타입으로 돌아갈 때 -----\n");
// 자식 클래스 타입의 객체 생성
Child2 child21 = new Child2();
child21.field1 = "Parent2에서 상속받은 멤버 변수";
child21.field2 = "Child2 전용으로 가지고 있는 멤버 변수";
System.out.println("객체 child21의 field1 출력: " + child21.field1);
System.out.println("객체 child21의 field2 출력: " + child21.field2);
System.out.println("객체 child21의 method1() 실행");
child21.method1();
System.out.println("객체 child21의 method2() 실행");
child21.method2();
System.out.println("객체 child21의 method3() 실행");
child21.method3();
System.out.println("\n부모 객체로 자동 타입 변환\n");
Parent2 parent21 = child21; // child21을 parent21에 대입
System.out.println("객체 parent21의 filed1 출력 : " + parent21.field1);
//에러 System.out.println("객체 parent21의 filed2 출력 : " + parent21.field2);
System.out.println("객체 parent21의 method1() 실행");
parent21.method1();
System.out.println("객체 parent21의 method2() 실행");
parent21.method2();
System.out.println("객체 parent21의 method3() 실행");
//에러 parent21.method3();
System.out.println("\nparent21을 다시 자식 클래스 타입으로 변환\n");
// 자식 클래스 타입의 변수에 부모 클래스 타입의 갹체를 대입하면 오류 발생
// 원본 객체를 자식클래스 타입의 변수로 타입 변환 시 해당 객체의 모든 멤버를 가지고 있는지 알 수 없기 때문에 강제 타입변환을 해야 함
//오류 Child2 child22 = parent21;
Child2 child22 = (Child2)parent21; // 강제 형변환
System.out.println("객체 child22의 field1 출력: " + child22.field1);
System.out.println("객체 child22의 field2 출력: " + child22.field2);
System.out.println("객체 child22의 method1() 실행");
child22.method1();
System.out.println("객체 child22의 method2() 실행");
child22.method2();
System.out.println("객체 child22의 method3() 실행");
child22.method3();
System.out.println("\n다시 자식 클래스 타입으로 변환되는 조건\n");
// 1. 원본이 자식 클래스 타입이어야 해당하는 자식 클래스 타입으로 변환이 가능
/*// 원본이 부모 클래스 타입
Parent2 parent23 = new Parent2();
// 자식 클래스 타입의 변수 선언
Child2 child23;
// 자식 클래스 타입의 변수에 부모 클래스 타입의 객체를 대입
child23 = (Child2) parent23; // 문법상으로는 문제없지만 실행하면 오류 발생! why? 원본이 부모 클래스 타입이라서.
// child23 객체는 부모클래스 parent2의 자식 클래스이기때문에 문법상의 오류는 없지만
// 원본이 자식 클래스 타입의 객체가 아니기 때문에 로직 에러(런타임 에러)가 발생함
// 자식 클래스 타입의 객체의 멤버 사용
child23.method3();*/
Parent2 parent24 = new Child2();
castMethod1(parent24);
castMethod2(parent24);
Parent2 parent25 = new Parent2();
castMethod1(parent25); // Child2로 변환되지 않음
castMethod2(parent25); // 런타임에러 발생
}
public static void castMethod1(Parent2 parent) {
// instanceof 연산자를 사용하면 현재의 객체가 지정한 타입의 객체인지 확인이 가능함.
if (parent instanceof Child2) {
Child2 child = (Child2) parent;
System.out.println("castMethod1 - Child2로 변환 성공");
}
else {
System.out.println("castMethod1 - Child2로 변환되지 않음");
}
}
public static void castMethod2(Parent2 parent) {
// 원본 객체가 변환하려는 클래스 타입의 객체가 아닐 수 있기 때문에 오류가 발생할 수 있음.
Child2 child = (Child2) parent;
System.out.println("castMethod2 - Child2로 변환 성공");
}
}