7.상속

클래스들의 관계 상속
다형성이 가장 중요하다.

7.4 다형성

7.4.1 자동형변환

다형성은 생물학에서 가져온 것으로 이것이 코드에 반영이된다.
밝은색 재규어는 재규어이다. 하위클래스의 인스턴스는 상위클래스의 기능을 다 사용할 수 있다.
자동으로 들어간다. 만약 기능을 재정의하면 재정의된 메소드가 실행된다.
참조변수의 타입이 중요한게 아니라 실제 인스턴스가 중요하다.
o1 을 만들면 그 변수에 SubClass01객체주소가 담김
-> o2에 넣으면 이 주소를 복사함
-> 각 메소드 실행시 결국 같은걸 실행하는 것임

public class C01Polymorphsim {
    public static void main(String[] args) {
        SubClass01 o1 = new SubClass01();
        SuperClass01 o2 = o1;
        o2.method1(); //sub method1
    }
}

class SuperClass01 {
    public void method1() {
        System.out.println("super method1");
    }
}

class SubClass01 extends SuperClass01 {
    @Override
    public void method1() {
        System.out.println("sub method1");
    }
}

7.4.2 자동형변환 -2

실제인스턴스가 중요하니 부모타입에 자식타입을 넣엇을때 자식타입의 메소드를 다 사용가능한가?
불가능하다.

public class C02Polymorphsim {
    public static void main(String[] args) {
        SubClass02 o1 = new SubClass02();
        o1.method1();
        o1.method2();

        SuperClass02 o2 = o1;

        o2.method1();
        //o2.method2(); 불가능
    }
}

동물 호흡하다()
말 호흡하다()달리다() 잉어호흡하다() 헤엄치다()
말을 동물의 입장에서 보앗을때 말은 달리다라는 기능이있지만
동물의 입장에서 보면 달리다라는게 잇을 수도 없을수도 잇어서 실행시킬수없다.
동물의 입장에서 말이 올지 잉어가 올지 모른다는 것이다.

SuperClass02 o3 = new SubClass022();이런식으로 햇을때
SuperClass02 o3 참조변수만의 입장에서 02이왓는지 02가 왓는지 확실할 수없다.

7.4.3 자동형변환 -3

String 클래스 Object클래슬르 상속받고있다.

public class C03Polymorphsim {
    public static void main(String[] args) {
        String s1 = "hello";
        Object o1 = s1;

        Object o2 = "java";

        char c1 = s1.charAt(0);
        // o1.charAt(0); 불가능
    }
}

7.4.4 확인문제 8번

SnowTire가 Tire를 상속받고 재정의햇을때 메소드를 실행시키면 어떤 결과가 나오는가
참조하는 객체가 SnowTire()이기 때문에 SnowTire의 재정의된 메소드가 실행된다.

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

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

7.4.5 다형성

public class C05Polymorphism {
    public static void main(String[] args) {
        Hero hero = new Hero();
        // .. 진행..

        hero.weapon = new Gun();
        hero.button1();

        // .. 진행..
        hero.weapon = new Bow();
        hero.button1();

        // .. 진행..
        hero.weapon = new Sword();
        hero.button1();
    }
}

class Sword extends Weapon {
    @Override
    public void attack() {
        System.out.println("검을 휘두릅니다.");
    }
}

class Bow extends Weapon {
    @Override
    public void attack() {
        System.out.println("활을 쏩니다.");
    }
}

class Hero {
    public Weapon weapon;

    public void button1() {
        weapon.attack();
    }
}

class Weapon {
    public void attack() {
        System.out.println("공격합니다.");
    }
}

class Gun extends Weapon {
    @Override
    public void attack() {
        System.out.println("총으로 공격합니다.");
    }
}

7.4.6 다형성 - 2

public class C07Polymorphism {
    public static void main(String[] args) {
        Hero hero = new Hero();
        // ...진행...무기선택
        Weapon w = getWeapon(1);

        hero.weapon = w;

        hero.button1(); //총으로 공격합니다.
    }

    public static Weapon getWeapon(int choice) {
        switch (choice) {
        case 1 -> {
            return new Gun();
        }
        case 2 -> {
            return new Bow();
        }
        case 3 -> {
            return new Sword();
        }
        }
        return new Weapon();
    }
}

Weapon타입에 상속받은 클래스들이 들어 갈 수있다는 것을 알게 되었다.
그래서 리턴값에 각 값들을 넣어주고 hero의 필드에 값을 넣으면 각 객체들이 들어가게 된다.
그래서 각 객체의 오버라이딩된 메소드들이 실행되게 되는 것이다.

7.4.7 다형성 - 3

Weapon배열에 각 객체들을 담을 수 있다.

public class C09Polymorphism {
    public static void main(String[] args) {
        Weapon[] o5 = new Weapon[5];
        o5[0] = new Weapon();
        o5[1] = new Gun();
        o5[2] = new Bow();
        o5[3] = new Sword();

        o5[0].attack(); //공격합니다.
        o5[1].attack(); //총으로 공격합니다.
        o5[2].attack(); //활을 쏩니다.
        o5[3].attack(); //검을 휘두릅니다.
    }
}

7.5 다형성 강제형변환

부모타입으로 받았는데 자식클래스의 메소드를 실행시켜야할때 어떻게 해야하나?

Animal a1 = new Horse();
a1.breath();

Horse h1 = a1;
h1.run();

하면 되지않나 싶은데 Animal은 말이 아니라 Horse h1 = a1;에서 오류가 난다.
그래서 값을 잃어버릴각오를 하고 강제 형변환해서 사용하면 된다.

Horse h1 = (Horse) a1;
h1.run();

7.5.1 강제형변환 - 2

강제형변환을 사용하는 것은 위험하다. 왜일가?
자식클래스를 담았던것을 형변환하면 예외가 나지 않는다.
그런데 동물이 달리고 싶다고 말로 강제 형변환하면
즉 부모를 자식으로 강제 형변환하면 에러는 아니지만 말이 안된다.
함부로 작성을 하면안되고 주의에 주의를 하고 작성을하자.

public class C02Cast {
    public static void main(String[] args) {
        Super02 o1 = new Sub02();

        Sub02 o2 = (Sub02) o1;

        Super02 o3 = new Super02();

        Sub02 o4 = (Sub02) o3; // 예외발생

        System.out.println("실행 코드 이어짐...");
    }
}

7.6 instancof

자식클래스일때만 강제 형변환해서 자식의 메소드를 실행시키고싶다.
instacneof 연산자의 연산결과는 boolean이다.
왼쪽항 참조 변수, 오른쪽 항 Type을 넣는다.
왼쪽 항의 참조변수가 가리키는 객체가 오른쪽 항 type이면 true
아니면 false를 리턴한다.

public class C04Instanceof {
    public static void main(String[] args) {
        Sub04 o1 = new Sub04();

        boolean b1 = o1 instanceof Sub04;
        boolean b2 = o1 instanceof Super04;
        System.out.println(b1);// true
        System.out.println(b2);// true

        Super04 o2 = new Super04();
        boolean b3 = o2 instanceof Super04;
        boolean b4 = o2 instanceof Sub04;
        System.out.println(b3);// true
        System.out.println(b4); // false
    }
}

실제 인스턴스가 중요하다.
참조변수가 가리키고 있는 instance의 타입이 무엇인가를 물어보는 것이다.
Super05에 자동형변환이 되니 Sub05도 Super05도 들어갈 수 있다.
Sub05은 Super05가 될 수 잇으니 트루트루가 나온다.
근데 Super05은 Sub05가 될 수없으니 트루 폴스가 나온다.

public class C05Instanceof {
    public static void main(String[] args) {
        method1(new Sub05()); // true true

        method1(new Super05()); // true false
    }

    public static void method1(Super05 s) {
        System.out.println(s instanceof Super05); // true
        System.out.println(s instanceof Sub05); // 그때그때 다름.
    }
}

7.6.1 instanceof -2

public class C06Instanceof {
    public static void main(String[] args) {
        Super06 o1 = new Sub06();

        // Sub06의 method1 실행시키고 싶어서 강제타입변환해야함.
        if (o1 instanceof Sub06) {
            Sub06 o2 = (Sub06) o1;
            o2.method1();
        }
    }
}

코드가 짧을때는 그냥 강제형변환해도 어떤걸 하고 있는지 알 수 잇어서 문제가 안생기지만
코드가 길어졋을때를 생각해서 instanceof 비교 코드를 넣어주자.

7.6.2 pattern matching for instanceof

instanceof하는 일이 자주 있지는 않지만 이것을 사용하게 된다면 자주 사용하게 된다.
그래서 새로운 문법이 생겨났다.

if (o1 instanceof Sub08) {
    Sub08 o2 = (Sub08) o1;
    // o2의 메소드 실행
}

// pattern matching for instanceof
if (o1 instanceof Sub08 o2) {
    // o2의 메소드 실행
}

public class C09Instanceof {
    public static void main(String[] args) {
        action(new Animal());
        action(new Horse());
        action(new Fish());
    }

    public static void action(Animal a) {
        a.breath();

        if (a instanceof Horse h) {
            h.run();
        } else if (a instanceof Fish f) {
            f.swim();
        } else {
            System.out.println("말도 아니고 물고기도 아닙니다.");
        }
    }
}

7.6.3 확인문제 12번

들어온 객체가 C일때만 method2실행되게 하기

public class Example {
    public static void action(A a) {
        a.method1();
        if (a instanceof C c) {
            c.method2();
        }
    }

    public static void main(String[] args) {
        action(new A());
        action(new B());
        action(new C());
    }
}

7.7 추상클래스

동물과 말,잉어가 있을때 동물은 말과 잉어의 공통적인 기능을 가진 개념일뿐이다.
그래서 이 동물 클래스로 인스턴스를 만들지 못하게 하고 싶을때 추상클래스를 사용할 수 있다.
필드도 작성가능하고 메소드도 작성가능하다. 인스턴스화만 불가능하다.

public abstract class Animal {
}

public class C01Abstaract {
    public static void main(String[] args) {
        Animal a1 = new Horse();
        Animal a2 = new Fish();

        //Animal a3 = new Animal(); //x
    }
}

그러면 뭐하러 추상메소드를 만드나?
추상메소드(abstract method)
몸통(body)없는 메소드
추상메소드가 있는 클래스는 추상 클래스이어야한다.
상속받는 클래스에서 무조건 재정의해야한다.
객체를 호출햇을때 메소드가 구현됫다는 사실이 보장이 되어야하기 때문이다.

추상메소드는 꼭 재정의 되어야한다.
만약 추상메소드를 재정의 하지 않으면
추상메소드를 가지고 있는거니 abstract해줘야 한다.

public abstract class Animal {
    public void see() {
        System.out.println("눈으로 봅니다.");
    }

    abstract void breath();
}

public class Horse extends Animal {
    // 추상메소드는 꼭 재정의 되어야한다.
    @Override
    void breath() {
        System.out.println("폐로 호흡합니다.");
    }
}

public abstract class Fish extends Animal {
}

7.7.1 확인문제 10번

Computer클래스에서 컴파일에러가 발생하는 이유?

public abstract class Computer {
    public void powerOn() {};
    public void poewerOff() {};
    public abstract void work();
}

public class Computer extends Machine{
}

-> 부모의 추상메소드를 재정의 하지 않았기때문에 컴파일 에러가 발생한다.
work()메소드를 재정의하면 오류가 나지 않는다.

7.7.2 다형성 re

Number클래스가 추상클래스이다. 이것을 상속받은 클래스들이 Number의 추상메소드들을 구현하고 있다.
어떤 것이 매개변수로 오더라도 구현이 되어 있다면 알아서 실행된다.
api를 보고 해석하는 방법을 알아두는 것이 중요하다.
값이 중요한게 아니라 상속관게로 매개변수에 들어가서 메소드가 실행이 된다는 것을 기억해두자.

public class C02Polymorphism {
    public static void main(String[] args) {
        Integer i1 = new Integer("66");
        printIntger(i1);

        Double d2 = new Double(3.14);
        printIntger(d2);

        BigDecimal b2 = new BigDecimal(3.1415);
        printIntger(b2);
    }

    public static void printIntger(Number n) {
        int intNum = n.intValue();
        System.out.println(intNum);
    }
}

2023.03.06 후기

db공부를 시작할것이다.
오라클로는 한번봣엇는데 mysql을 사용해서 해당강의를 복습해보고자한다.
중간중간 다른 문법을 찾아보면서 공부하면 될 듯하다.
대충봣을땐 거의 비슷한 문법을 가지고 있다.
타입은 일단 차이나고 페이징할대 범위도 차이가 약간잇엇다.
페이징 시 쿼리 LIMIT, OFFSET등 다른문법을 꽤 봐서 따로 공부하고자 했는데 딱히 좋은 강의를 찾지 못하고 많은 차이가 없어보인다.
하나의 관계형데이터베이스를 잘알게 되면 다른 관계형데이터베이스도 잘 알 수 있다는 생활코딩님의 말을 통해 혼자서 공부해보기로 했다.

그렇지만 남에게 휘둘리기 시작했다. 힘들다.
매일이 두렵다. 다음 날이 오는게 두렵다. 고민을 하지만 나아지는게 없다.
나만의 페이스로 가야한다. 휘둘리지말고 꺾이지 않는 마음으로...

'국비 > Java' 카테고리의 다른 글

2023.03.09 30일차 Java  (0) 2023.03.09
2023.03.08 29일차 Java  (0) 2023.03.08
2023.03.03 26일차 Java  (0) 2023.03.06
2023.03.02 25일차 Java  (0) 2023.03.02
2023.02.28 24일차 Java  (0) 2023.02.28

+ Recent posts