3월 ~ 5월) 자바/java

10Day - (상속) Car & CarApp & Engine / Member & MemberApp & MemberCastApp & MemberEvent & MemberEventApp

첼로그 2023. 4. 11. 10:52
// 클래스와 클래스의 관계 - 객체 관계
// > UML (Unified Modeling Languaage) 를 사용하여 클래스 다이어그램으로 표현(Class Diagram)으로 표현
// 1. 일반화 관계 (Generalization) - 상속 관계 - X is a Y
// > 클레스를 선언할때 기존 클래스를 상속받아 작성
// > 사원 클래스와 관리자 클래스의 관계 - 관리자는 사원이다. (0) / 사원은 관리자다. (X)
// 2. 실체화 관계 (Realization) - 상속 관계
// > 클래스를 선언할때 기존 인터페이스를 상속받아 작성
// > 인터페이스 - 현실에 존재하는 대상을 클래스보다 추상적으로 표현하기 위한 자료형
// 3. 연관 관계 (Association) - 포함 관계 - X has a Y
// > 직접 연관 관계 (Direct Association) - 한 방향으로만 도구로써 기능을 제공하는 관계
// > 컴퓨터 << CPU + MatinBoard + Mermory
// 4. 집합 연관 관계 (Aggregation) - 포함 관계로 설정된 객체들의 생명주기가 다른 포함 관계
// 컴퓨터 - 프린터 관계
// 5. 복합 연관 관계 (Aggregation) - 포함 관계로 설정된 객체들의 생명주기가 같은 포함 관계
// 게임 - 캐릭터 관계
// 6. 의존 관계 (Dependency) - 포함 관계로 설정된 객체를 변경되도 다른 객체에 영향을 주지않는 포함관계
// TV - 리모콘 관계

 310p

 

association

Car

public class Car {
    private String modelName;
    private int productionYear;
    // 엔진정보를 저장하기 위한 필드 - Engine 클래스를 자료형으로 선언된 필드
    // > 필드에는 생성자 또는 Setter 메소드를 사용하여 Engine 객체를 제공받아 저장 - 포함관계
    private Engine carEngine; // 포함관계


    public Car() {

    }

    // ▽ 생성자, getter setter
    public Car(String modelName, int productionYear, Engine carEngine) {
        super();
        this.modelName = modelName;
        this.productionYear = productionYear;
        this.carEngine = carEngine;
    }

    public String getModelName() {
        return modelName;
    }

    public void setModelName(String modelName) {
        this.modelName = modelName;
    }

    public int getProductionYear() {
        return productionYear;
    }

    public void setProductionYear(int productionYear) {
        this.productionYear = productionYear;
    }

    public Engine getCarEngine() {
        return carEngine;
    }

    public void setCarEngine(Engine carEngine) {
        this.carEngine = carEngine;
    }
    // △ 생성자와 get set

    // 자동차 정보(필드값)를 출력하는 메소드
    public void displayCar() {
        System.out.println("모델명 = " + modelName);
        System.out.println("생산년도 = " + productionYear);

        // System.out.println("엔진정보 = " + carEngine); // 객체의 메모리 주소 출력
        // 필드에 저장된 객체를 이용하여 메소드 호출
        // > 포함관계로 설정된 클래스(객체)의 메소드를 호출하여 원하는 기능 구현
        //

//        System.out.println("엔진정보 = " + carEngine);
//        System.out.println("배기량 = " + carEngine.getDisplacement());
        carEngine.displayEngine(); // 코드의 중복성 최소화

    }
}

Engine

// 엔진 정보(연료타입, 배기량)를 저장하기 위한 클래스
public class Engine {
    private String fualType;
    private int displacement;

    public Engine() {
        // TODO Auto-generated constructor stub
    }

    // con 생성자와 setter & getter
    public Engine(String fualType, int displacement) {
        super();
        this.fualType = fualType;
        this.displacement = displacement;

    }
    public String getFualType() {
        return fualType;
    }

    public void setFualType(String fualType) {
        this.fualType = fualType;
    }

    public int getDisplacement() {
        return displacement;
    }

    public void setDisplacement(int displacement) {
        this.displacement = displacement;
    }
    // alt + insert 로 만들어진것들 △


    // 엔진정보(필드값)를 출력하는 메소드
    public void displayEngine() {
        System.out.println("연료타입 = " + fualType);
        System.out.println("배기량 = " + displacement);

    }
}

 


CarApp

public class CarApp {
    public static void main(String[] args) {
        // 엔진 생성
        Engine engine = new Engine();

        engine.setFualType("경유");
        engine.setDisplacement(2000);

        // engine.displayEngine();

        // 자동차 생성
        Car carOne = new Car();


        carOne.setModelName("쏘렌트");
        carOne.setProductionYear(2020);

        // Setter 메소도를 호출하여 매개변수에 엔진정보를 전달받아 필드에 저장 > 인위적인 포함관계 성립
        carOne.setCarEngine(engine);

        carOne.displayCar();

        System.out.println("=============================================================");
        //자동차 생성 >> 엔진을 생성하여 필드에 저장 - 인위적인 포함관계 성립
        // => 생성자를 호출하여 매개변수에 엔진정보(Engine 객체)를 전달받아 필드에 저장
        Car carTwo=new Car("싼타페", 2023, new Engine("휘발유", 3000));

        carTwo.displayCar();
        System.out.println("=============================================================");
        System.out.println(carOne.getModelName()+"의 엔진정보 >> ");
        engine.displayEngine();
        System.out.println("=============================================================");
        System.out.println(carTwo.getModelName()+"의 엔진정보 >> ");
        //자동차(Car 객체)에 저장된 엔진정보(engine 필드값 - Engine 객체)를 Getter 메소드로
        //반환받아 Engine 객체의 메소드 호출
        carTwo.getCarEngine().displayEngine();
    }
}

모델명 = 쏘렌트
생산년도 = 2020
연료타입 = 경유
배기량 = 2000
=============================================================
모델명 = 싼타페
생산년도 = 2023
연료타입 = 휘발유
배기량 = 3000
=============================================================
쏘렌트의 엔진정보 >> 
연료타입 = 경유
배기량 = 2000
=============================================================
싼타페의 엔진정보 >> 
연료타입 = 휘발유
배기량 = 3000

 


inheritcance

Member

// 회원정보(아이디, 이름)를 저장하기위한 클래스
public class Member {
    private String id;
    private String name;

    public Member () {

    }

    // ▽ 생성자, get&set
    public Member(String id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void display() {
        System.out.println("아이디 = " + id);
        System.out.println("이름 = " + name);
    }
}

 


MemberApp

public class MemberApp {
    public static void main(String[] args) {
        Member member1 = new Member();

        member1.setId("abc123");
        member1.setName("홍길동");

        member1.display();
        System.out.println("--------------------------------------------------");
        Member member2=new Member("xyz789", "임꺽정");
        member2.display();
    }
}


아이디 = abc123
이름 = 홍길동
--------------------------------------------------
아이디 = xyz789
이름 = 임꺽정

 

 


 

// 상속(Inheritance) - 클래스를 선언할때 기존 클래스를 물려받아 사용하는 기능
// > 기존 클래스를 재활용하여 새로운 클래스를 쉽게 빠르게 작성
// > 코드의 중복성을 최소화하여 프로그램 생산성 및 유지보스의 효율성 증가
// > 공통적인 속성과 행위를 포함한 다수의 클래스를 선언할 때, 공통적인 속성과 행위가 선언된 클래스를 선언하고 작성된 클래스를 상속받아 사용

// 이벤트 관련 회원정보 (아이디, 이름, 이메일)을 저장하기 위한 클래스
// > 회원정보를 저장하기 위한 Member 클래스를 상속받아 작성하는 것을 권장 - 재사용성 증가

// 물려주는 클래스 - 부모, 선조, 기본, 슈퍼클래스
// 물려받는 클래스 - 자식, 후손, 파생, 서브클래스

// 형식) public class 자식클래스 extends 부모클래스 {
// 자식클래스에서는 부모클래스의 필드 또는 메소드 사용 가능
// ...
// }

MemberEvent

// 부모클래스의 생성자는 자식클래스에게 상속되지 않으며 부모클래스의 은닉화 선언된 피륻와 메소드는 자식 클래스에서 접근불가능

// 자식클래스의 생성자로 객체를 생성할 경우 부모클래스의 생성자가 먼저 호출되어
public class MemberEvent extends Member {
    /*
    // 부모클래스(Member)를 상속받은 필드 또는 메소드 미선언
    private String id;
    private String name;
     */
    private String email;

    public MemberEvent() {
        // super();//부모클래스의 매개변수가 없는 기본 생성자 호출 - 생략 가능
    }

    // super - 자식클래스의 메소드에서 부모클래스 객체의 메모리 주소를 저장하기위한 키워드
    // > 자식클래스의 메소드에서 부모클래스 객체의 필드 또는 메소드를 참조하기 위해 사용
    // > 자식클래스의 메소드에서 super 키워드를 사용하지 않아도 자식 클래스의 메소드에서는 this 키워드로
    // 참조되는 필드와 메소드가 없으면 자동으로 부모클래스 객체의 필드 또는 메소드를 참조

    // super 키워드를 사용하는 경우
    // 1. 자식클래스의 생성자에서 부모클래스의 생성자를 호출하여 초기화 처리하기 위해 super 키워드 사용
    // 형식) super(값, 값, ...);
    // > 생략된 경우 부모클래스의 매개변수가 없는 기본 생성자를 호출하여 객체 생성
    // > 생성자에서 다른 생성자를 호출하는 명령은 반드시 첫번째 명령으로 작성
    //2.자식클래스의 메소드에서 오버라이드 선언되어 숨겨진 부모클래스의 메소드를 호출할 경우 super 키워드 사용

    /*
    public MemberEvent(String id, String name, String email) {
        // super();
        // 자식클래스의 메소드에서는 this 키워드로 자식클래스 객체의 필드 또는 메소드를 참조하고
        // 자식클래스 객체의 필드 또는 메소드가 없는 경우 super 키워드를 이용하여 부모클래스 객체의 필드 또는 메소드 참조
		// > 부모클래스의 필드 또는 메소드가 은닉화 선언된 경우 자식클래스에서 접근 불가능
		// this.id = id;
		setId(id);
		// this.name = name;
		setName(name);
		this.email = email;
    }
    */

    // Alt + Shift + s > 팝업메뉴 - c > 부모클래스의 생성자 선택(안해주면 기본생성자) > 필드 선택 > Generation
    public MemberEvent(String id, String name, String email) {
        super(id, name); // 부모클래스의 매개변수가 있는 생성자 호출
        this.email = email;
    }

    /*
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

     */

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    //메소드 오버라이딩(Method Overriding) : 상속 관계에서 부모클래스의 메소드를 자식 클래스에서 재선언하는 기능
    // > 부모클래스의 메소드를 자식클래스의 객체가 사용하기 부적절한 경우 부모클래스의 메소드를 자식클래스에서 재선언하여 사용하는 방법
    // > 부모클래스의 메소드(Hide Method)는 숨겨지고 자식클래스의 메소드만 접근 가능
    // 메소드 오버라이등의 작성 규칙 - 부모클래스의 메소드와 같은 접근제한자, 반환형, 메소드명, 매개변수, 예외 전달을 사용하여 자식클래스의 메소드 작성
	/*

    public void display() {
        // System.out.println("아이디 = "+id);
        System.out.println("아이디 = " + getId());
        // System.out.println("이름 = " + name);
        System.out.println("이름 = " + getName());
        System.out.println("이메일 = " + email);
    }

 */

    // 이클립스에서는 부모클0래스의 메소드를 자식클래스에서 오버라이드 선언되도록 자동하는 기능 제공
    // > 오버라이드 선언하고 싶은 부모클래스의 메소드명 입력 >> ctrl + space > Override Method 선택
    //@Override : 오버라이드 선언된 메소드를 표현하기 위한 어노테이션
    //어노테이션(Annotation) : API 문서에서 특별한 설명을 제공하기 위한 기능의 자료형(인터페이스)
    // > Java Source 작성에 필요한 특별한 기능을 제공하기 위한 사용되는 어노테이션
    // > @Override, @Deprecated, @SuppressWarings
    @Override
    public void display() {
        super.display();//super 키워드로 부모클래스의 숨겨진 메소드 호출
        System.out.println("이메일 = " + email);
    }
}

 

 


MemberEventApp

public class MemberEventApp {
    public static void main(String[] args) {

        // 자식클래스의 생성자로 객체를 생성할 경우 부모클래스 (Member)의 생성자가
        // 먼저 호출되어 부모클래스의 객체가 먼전 생성된 후 자식클래스의 생성자로 객체를 생성하여 상속관계 자동으로 성립
        // > 자식클래스의 참조변수에는 자식 클래스 객체의 메모리 주소 저장하여 자식클래스 객체의 요소를 참조하지만,
        // 상속관계에 의해 부모클래스 객체의 요소 또는 메소드 참조 가능

        MemberEvent member1 = new MemberEvent();

        member1.setId("abc123");
        member1.setName("홍길동");
        member1.setEmail("abc@itwill.xyz"); // 자식꺼

        member1.display(); // 자식꺼

        System.out.println("-----------------------------------------------");
        MemberEvent member2 = new MemberEvent("xyz789" , "임꺽정" , "xyz@itwill.xyz");
        member2.display();
    }
}

아이디 = abc123
이름 = 홍길동
이메일 = abc@itwill.xyz
-----------------------------------------------
아이디 = xyz789
이름 = 임꺽정
이메일 = xyz@itwill.xyz

 


MemberCastApp

public class MemberCastApp {
    public static void main(String[] args) {
        // 부모크래스 참조변수 = new 부모클래스 ();
        // > 부모클래스의 생성자로 객체를 생성하여 부모클래스의 참조변수에 저장 - 가능
        Member member1 = new Member();

        // 참조변수에 저장된 부모클래스의 객체를 사용하여 부모클래스의 메소드 호출
        member1.setId("abc123");
        member1.setName("홍길동");

        member1.display();
        System.out.println("-------------------------------------------");
        // 자식 클래스 참조변수 = new 자식클래스();
        // > 부모클래스의 생성자로 부모클래스 객체를 생성하고 자식클래스의 생성자로
        // 자식 클래스 객체를 생성하여 자식클래스의 참조변수에 자식클래스이 객체 저장

        MemberEvent member2 = new MemberEvent();

        // 참조변수에 저장된 자식클래스의 객체를 사용하여 자식클래스의 메소드를 호출할수 있으며
        // 상속관계에 의해 부모클래스 객체를 참조하여 부모클래스도 호출 가능

        member2.setId("xyz789");
        member2.setName("임꺽정");
        member2.setEmail("xyz@itwill.xyz");

        member2.display();
        System.out.println("-----------------------------------");
        // 자식클래스 참조변수 = new 부모클래스();
        // > 부모클래스의 생성자로 부모클래스 객체를 생성하고 자식클래스의 참조변수에 부모 클래스의 객체 저장 - 불가능 (에러발생)

        // MemberEvent member3 = new Member();
        System.out.println("-----------------------------------");
        // 부모클래스 참조변수 = new 자식클래스();
        // > 부모클래스의 생성자로 부모클래스 객체를 생성하고 자식클래스의 참조변수에 부모 클래스의 객체 저장 - 가능
        // 클래스 객체를 생성하여 부모클래스의 참조변수에 부모클래스의 객체 저장 - 가능
        Member member4 = new MemberEvent(); // member4 에는 부모클래스 저장

        // 참조변수에 저장된 부모클래스의 객체를 사용하여 부모클래스의 메소드를 호출 가능
        // > 참조변수로 자식클래스 객체를 참조할수 없으므로 자식클래스도 호출 불가능

        member4.setId("opq456");
        member4.setName("전우치");

        // 객체 형변환을 이용하면 부모클래스의 참조변수로 자식클래스의 메소드 호출 가능
        // > 명시적 객체 형변환(강제 형변환), 묵시적 객체 형변환(자동 형변환)
        // > 상속관계의 클래스에서만 객체 현변환 사용 가능

        // 명시적 객체 형변환 : Cast연산자를 사용하여 부모클래스 참조변수의 자료형을 자식 클래스로
        // 변경하면 일시적으로 참조변수에 자식클래스의 객체가 자동 저장
        // > 명시적 객체 형변환에 의해 자식클래스로 자료형이 변경된 참조변수는 자식클래스의 객체가 저장되므로 자식클래스의 메소드 호출
        /*
        MemberEvent event = (MemberEvent) member4;
        event.setEmail("opq@itwill.xyz");
         */

        // 객체 . 연산자보다 Cast 연산자가 먼저 실행되도록 () 연산자 사용
        ((MemberEvent)member4).setEmail("opq@itwill.xyz");

        //((MemberEvent)member4).display();
        // 묵시적 객체 형변환 - 부모클래스의 메소드를 자식클래스에서 오버라이드 선언하면
        // 부모클래스의 메소드의 숨겨진 메소드 대신 자식클래스의 메소드를 호출하기 위해 참조변수의 자료형을 자동으로
        // 자식클래스로 변경하여 일시적으로 자식클래스의 객체가 참조변수에 저장되어 자식클래스의 메소드 호출
        member4.display();
        System.out.println("--------------------------------------");

    }
}


아이디 = abc123
이름 = 홍길동
-------------------------------------------
아이디 = xyz789
이름 = 임꺽정
이메일 = xyz@itwill.xyz
-----------------------------------
-----------------------------------
아이디 = opq456
이름 = 전우치
이메일 = opq@itwill.xyz

 

 

 

this 객체참조
super 부모 클래스 참조

this 찾아도 없으면 super 사용한다