열심히 끝까지

Java1 day07 본문

Java1(주말)

Java1 day07

노유림 2022. 4. 30. 19:00

[7일차 수업 내용]
1. 상속
2. 오버라이딩
====================================================================
1. 상속 ( inheritance )
            1-1 ) 상속의 정의와 장점
                        - 상속이란 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것
                        - 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고,
                          코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이
                                    ==> 코드의 재사용성을 높이고 코드의 중복을 제거하여 
                                           프로그램의 생성성과 유지보수에 크게 기여
                        - 상속을 구현하기 위해선 새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는 

                          클래스의 이름을 키워드 extends와 함께 써 주기만 하면 됨

                                    Ex) class Child extends Parents{ }

                                    조상클래스             부모(parent)클래스, 상위(super)클래스, 기반(base)
                                    자손클래스             자식(child)클래스, 하위(sub)클래스, 파생된(derived)클래스

                       - 생성자와 초기화블록은 상속되지 않으며 멤버만 상속
                       - 자손클래스의 멤버 개수는 조상클래스보다 항상 같거나 많음
                       - 자손클래스의 인스턴스를 생성하면 조상클래스의 멤버와 자손클래스의 멤버가 합쳐진
                         하나의 인스턴스가 생성

            1-2 ) 클래스간의 관계 - 포함관계
                       - 상속이외에도 클래스를 재사용하는 또 다른 방법이 있는데 
                         그것은 클래스간에 포함관계를 맺어주는 것
                       - 클래스간의 포함관계를 맺어 주는 것은 한 클래스의 멤버변수로 
                         다른 클래스 타입의 창조변수를 선언하는 것을 뜻함

                        class C extends A, B{ }        (X)
                        class C extends A{
                                 B, b;
                        }

                       - 클래스를 작성하는 데 있어서 상속관계를 맺어 줄 것인지 
                         포함관계를 맺어줄 것인지 결정하는 것은 때때로 혼란스러움

                                상속관계                                '~은 ~이다(is -a)'
                                포함관계                                '~은 ~을 가지고 있다.(has -a)'

                                원(Circle), 점(Point)
                                원(Circle)은 점(Point)                            ==> Circle is a Point
                                원(Circle)은 점(Point)을 가지고 있다.         ==> Circle has a Point      ==> 포함관계

            1-3 ) 단일상속
                       - 다른 객체지향언어인 C++에선 다중상속을 허용하지만 
                         자바에서는 오직 단일상속만을 허용
                       - 예를 들어 TV 클래스와 VCR클래스가 있을 때 
                         두 클래스로부터 상속을 받는 TVCR클래스를 작성할 수 없음
                       만약 다중상속이 허용된다고 할 때 두 클래스 모두 power()라는 메소드가 있다면 
                       어느 조상클래스의 power()를 상속받게 되는 것일까?
                       - 자바에서는 다중상속의 이러한 문제점을 해결하기 위해 
                         다중상속의 장점을 포기하고 단일상속만 허용
                                       ==> 이럴 때 포함관계를 사용 가능

           1-4 ) Object클래스 - 모든 클래스의 조상
                       - Object 클래스는 모든 클래스의 상송계층도의 최상위에 있는 조상클래스
                       - 자바의 모든 클래스들은 Object클래스의 멤버들을 상속받기 때문에 
                         Object클래스에 정의된 멤버들을 사용할 수 있음

============================================================================
2. 오버라이딩 ( overriding )
            2-1 ) 오버라이딩이란?
                        - 조상클래스로부터 상속받은 메소드의 내용을 변경하는 것을 
                          오버라이딩이라고 한다.
                        - 상속받은 메소드를 그대로 사용하기도 하지만,  
                          자손클래스 자신에 맞게 변경해야 하는 경우가 많음
                                     ==> 이럴 때 조상의 메소드를 오버라이딩

            2-2 ) 오버라이딩의 조건
                        - 자손클래스에서 오버라이딩하는 메소드는 
                          조상클래스의 메소드의 이름, 매개변수, 반환타입이 같아야 함(선언부 변경 X)

                        ① 접근제어자는 조상클래스의 메소드보다 좁은 범위로 변경할 수 없음
                                    - 만일 조상클래스의 정의된 메소드의 접근제어자가 protected라면 
                                      이를 오버라이딩하는 자손클래스의 메소드는 
                                      접근제어자가 protected 또는 public이어야 함
                                      ( 대부분 같은 접근 제어자를 사용한다 )
                        ② 조상클래스의 메소드보다 많은 수의 예외를 선언할 수 없음
                        ③ 인스턴스메소드를 static 메소드 또는 그 반대로 변경할 수 없

            2-3 ) 오버로딩 vs 오버라이딩 **
                        - 오버로딩은 기존에 없는 새로운 메소드를 추가하는 것,
                          오버라이딩은 조상으로부터 상속받은 메소드의 내용을 변경하는 것
                       
                        * 오버로딩( overloading )         : 기존에 없는 새로운 메소드를 정의하는 것( new )
                        * 오버라이딩( overriding )        : 상속받은 메소드의 내용을 변경하는 것( change, modify )

            2-4 ) super
                       -  super는 자손클래스에서 조상클래스로부터 
                          상속받은 멤버를 참조하는데 사용되는 참조변수
                       - 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이
                         상속받은 멤버와 자신의 멤버와 이름이 같을 때는 super를 붙여서 구분할 수 있음
                       - 조상클래스로부터 상속받은 멤버도 클래스 자신의 멤버이므로 super대신 this를 사용할 수 있음
                       - 그래도 조상클래스의 멤버와 자손클래스의 멤버가 중복정의되어서 서로 구별해야 하는 경우에만
                         super를 사용하는 것이 좋음
        
            2-5 ) super()
                       - this()와 마찬가지로 super()역시 생성자이다.
                       - this()는 같은 클래스의 다른 생성자를 호출하지만 
                         super()는 조상클래스의 생성자를 호출하는데 사용
                       - 자손클래스의 인스턴스를 생성하면, 
                         자손의 멤버와 조상의 멤버가 합쳐진 하나의 인스턴스가 생성됨
                       - 이 때 조상클래스의 멤버의 초기화작업이 수행되어야하기 때문에 
                         자손클래스의 생성자에서 조상클래스의 생성자가 호출되어야 함
                       - 생성자의 첫줄에서 조상클래스의 생성자를 호출하는 이유는 
                         자손클래스의 멤버가 조상클래스의 멤버를 사용할 수도 있으므로
                         조상의 멤버들이 먼저 초기화 되어있어야 함



============================================================================

package example01;
public class Bicycle {
            int id;
            String brand;
            String owner;
}
--------------------
package example01;

public class MountainBicycle extends Bicycle{
            String frame;
            int gear;
            int price;
            String sector;

            void info() {
                        System.out.println("id : " + this.id);
                        System.out.println("brand : " + this.brand);
                        System.out.println("owner : " + this.owner);
                        System.out.println("frame : " + this.frame);
                        System.out.println("gear : " + this.gear);
                        System.out.println("price : " + this.price);
                        System.out.println("sector : " + this.sector);
            }
            public static void main(String[] args) {
                        MountainBicycle mb = new MountainBicycle();

                        mb.id = 1111;
                        mb.brand = "삼천리";
                        mb.frame = "알루미늄";
                        mb.gear = 33;
                        mb.price = 300000;
                        mb.owner = "이용현";
                        mb.sector = "삼천리";
                        mb.info();
            }
}

------------------------------------------------------------------------
package example01;

public class VCR {
            boolean power;
            int counter = 0;

            void power() {
                        power = !power;
            }

            void play() {}
            void stop() {}
            void rew() {}
}

-------------------------------------
package example01;

public class Tv {
            boolean power;
            int channel;

            void power() {
                        power = !power;
            }

            void channelUp() {
                        channel++;
            }
            void channelDown() {
                        channel--;
            }
}
----------------------------------
package example01;

public class TVCR extends Tv{
            VCR vcr = new VCR();

            void play() {
                        vcr.play();
            }
            void stop() {
                        vcr.stop();
            }
            void rew() {
                        vcr.rew();
            }
            
            public static void main(String[] args) {
                        TVCR tc = new TVCR();
                        // Tv클래스에서 상속받은 멤버
                        tc.power(); 
                        tc.channelUp();
                        tc.channelDown();
                        // VCR의 멤버들을 사용하는 방법
                        tc.play();
                        tc.vcr.power();
            }
}
----------------------------------------------------------------------------
package example01;

public class InheritanceTest {
            public static void main(String[] args) {
                        Child c = new Child();
                        c.bye();
                        c.hello();
                        c.x = 15; 
                        c.y = 25;
                        System.out.println("c.x : " + c.x);
                        System.out.println("c.y : " + c.y);
                        System.out.println("c.z : " + c.z);
            }
}
class Child extends Parent{             // 멤버변수 5개 Parent 3, child 2
            int z = 15;

            void bye() {
                        System.out.println("Child의 bye()메소드");
            }
}
class Parent{             // 멤버변수 3개
            int x = 5;
            int y = 10;

            void hello() {
                        System.out.println("Parent의 hello()메소드");
            }
}
---------------------------------------------------------------------------------
package example02;

public class Point {
            int x;
            int y;

            // Point(){}

            Point(int x , int y){
                        this.x = x;
                        this.y = y;
            }

            String getLocation() {
                        return "x : " + x + ", y : " + y;
            }
}
-----------------------------
package example02;

public class PointTest {
            public static void main(String[] args) {
                        Point3D p3d = new Point3D(1, 2, 3);
                        System.out.println(p3d.getLocation());
            }
}
class Point3D extends Point{
            int z;
            // Point3D(){ super(); }
            public Point3D(int x, int y, int z) {
                        super(x, y);
                        // 조상클래스의 매개변수가 있는 생성자를 호출
                        // 자바에선 기본적으로 부모의 기본생성자(super())를 호출하지만
                        // 기본생성자가 없을 경우엔 부모클래스에서 기본생성자를 추가하거나
                        // 자손클래스에 부모클래스의 매개변수가 있는 생성자를 호출해야 한다.
                        this.z = z;
            }

            @Override
            String getLocation() {
            return "x : " + x + ", y : " + y + ", z : " + z;
            }
}
-------------------------------------
package example02;

public class SuperTest {
            public static void main(String[] args) {
                        Child c = new Child();
                        c.method();
                        System.out.println();
                        c.method2();
            }
}
class Parent{
            int x = 10;
            int y = 20;
}
class Child extends Parent{
            int y = 30;

            void method() {
                        System.out.println("x : " + x); // 10
                        System.out.println("x : " + this.x); // 10
                        System.out.println("x : " + super.x); // 10
            }

            void method2() {
                        System.out.println("y : " + y); // 30
                        System.out.println("y : " + this.y); // 30
                        System.out.println("y : " + super.y); // 20
            }
}
------------------------------------------------------------------------------------------
package example03;

public class DrawShape {
            public static void main(String[] args) {
                        Point centerP = new Point(150, 150);

                        // Circle(point center, int r) 생성자 호출
                        Circle c = new Circle(centerP, 50);
                        Circle c1 = new Circle(new Point(100, 100), 40);

                        c.draw();
                        c1.draw();


                        Point[] p = new Point[3];
                        p[0] = new Point(1,1);
                        p[1] = new Point(2,2);
                        p[2] = new Point(3,3);

                        Point[] p1 = {
                                    new Point(1,1),
                                    new Point(2,2),
                                    new Point(3,3)
                        };
                        Triangle t = new Triangle(p);
                        t.draw();
                        Triangle t1 = new Triangle(p1);
                        t1.draw();
            }
}
class Shape{
            String color = "black";

            void draw() {
                        System.out.println("[color : " + color +"]");
            }
}
class Point{
            int x, y;

            Point(){
                        this(0, 0);
            }

            Point(int x, int y){
                        this.x = x;
                        this.y = y;
            }

            String getXY() {
                        return "(" + x + "," + y + ")"; // Ex. (0,0)
            }
}
class Circle extends Shape{
            Point center;  // 좌표
            int r; //반지름

            Circle(Point center, int r){
                        this.center = center;
                        this.r = r;
            }
            Circle(){ // Point center = new Point(0,0);
                        this(new Point(0,0), 100);
            }
            @Override
            void draw() {
                        System.out.printf("[center=(%d,%d), r=%d, color=%s]\n", center.x, center.y, r,color);
            }
}
class Triangle extends Shape{
            Point[] p = new Point[3];     // p[0] = 10; p[1] = 2; p[2] = 20;

            Triangle(Point[] p) {
                        this.p = p;
            }
            @Override
            void draw() {
                        System.out.printf("[p1=%s, p2=%s, p3=%s, color=%s]\n",

                         p[0].getXY(), p[1].getXY(), p[2].getXY(), color);
            }
}
----------------------------------------------------------------------------------------------------------------
package example04;

public class Card {
            static final int KIND_MAX = 4; // 카드 무늬의 개수
            static final int NUM_MAX = 13; // 무늬별 카드 수

            // 무늬를 상수로 지정
            static final int CLOVER = 1;
            static final int HEART = 2;
            static final int DIAMOND = 3;
            static final int SPADE = 4;

            // 인스턴스 변수 선언
            int kind;
            int number;

            Card(int kind, int number){
                        this.kind = kind;
                        this.number = number;
            }

            @Override
            public String toString() {
                        String kind = "";          // 지역변수
                        String number = "";

                        // 무늬설정
                        switch(this.kind) { // 이 때, this.kind는 위에 int kind를 가리킴
                        case 1 :
                                    kind = "클로버";
                                    break;
                        case 2 :
                                    kind = "하트";
                                    break;
                        case 3 :
                                    kind = "다이아몬드";
                                    break;
                        case 4 :
                                    kind = "스페이드";
                                    break;
                        }

                        // 숫자설정
                        switch(this.number) {
                        case 11 : 
                                    number = "J";
                                    break;
                        case 12 : 
                                    number = "Q";
                                    break;
                        case 13 : 
                                    number = "K";
                                    break;
                        default :

                                    number = this.number + "";
                        }

                        return "무늬 : " + kind + ", 숫자 : " + number;
            }
}
-----------------------------
package example04;

public class Deck {

            final int CARD_NUM = 52;     // 카드의 개수

            Card[] card = new Card[CARD_NUM];

            int i = 0;

            // 인스턴스 초기화 블록
            {
                        // 52번 반복을 돌면서 카드를 초기화
                        for(int k = Card.KIND_MAX; k > 0; k--) {    // k : 1~4
                                    for(int n = 1; n < Card.NUM_MAX; n++) { // n : 1~13
                                                card[i++] = new Card(k, n);
                                    }
                        }
            }

            Deck() {}

            // 단순히 섞는 메소드
            public void shuffle() {
                        for(int n = 0; n < 1000; n++) {
                                    int i = (int)(Math.random() * CARD_NUM); // 0 ~ 51
                                    Card tmp = card[0];
                                    card[0] = card[1];
                                    card[1] = tmp;         // 교환법칙
                        }
            }

            // Deck에서 카드 하나를 임의로 선택
            public Card pick() {
                        int index = (int)(Math.random() * CARD_NUM); // 0 ~ 51
                        return pick(index);
            }

            // 지정된 위치(index)에 있는 카드 하나를 선택
            public Card pick(int index) {
                        if(0 <= index && index < CARD_NUM) {
                                    return card[index];
                        }else {
                                    return pick();
                        }
            }
}
-----------------------------
package example04;

public class DeckEx {
            public static void main(String[] args) {
                        Deck d = new Deck();
                        Card c = d.pick(51);

                        System.out.println("[카드 섞기 전에 제일 밑에 있는 카드]");
                        System.out.println(c.toString());

                        d.shuffle();
                        System.out.println();

                        c = d.pick(51);
                        System.out.println("[카드 섞은 후에 제일 밑에 있는 카드]");
                        System.out.println(c.toString());
                        System.out.println();

                        c = d.pick(200);
                        System.out.println(c.toString());
                        System.out.println();

                        c = d.pick();
                        System.out.println(c.toString());
            }
}

'Java1(주말)' 카테고리의 다른 글

Java1 day08  (0) 2022.05.01
Java1 day06  (0) 2022.04.24
Java1 day05 보충  (0) 2022.04.24
Java1 day05  (0) 2022.04.23
Java1 day04 보충  (0) 2022.04.23