본문 바로가기
교육/Java&Spring

kosta 클라우드 네이티브 애플리케이션 개발 과정 day 14

by Renechoi 2023. 1. 6.

kosta 클라우드 네이티브 애플리케이션 개발 과정 day 14


 

 

지난 시간 복습 ! 

 

오버라이딩 overriding 

- 상속 관계 

-> 왜 하느냐? 부모 클래스의 메서드를 자식 클래스에서 다시 재정의 ! 

-> 왜? 내게 적합하지 않기 때문에 

- 원칙 : 부모 메서드 시그니처는 일치해야 한다 ! 

 

-> 자바의 다형성을 표현한다 ! 

 

public class Dog{

	private String name; 
    
    public void bark();
}



public class BorderCollie extends Dog {
	
    @Override
    public void bark(){
    	sout("왈왈!")
    }
}


public class Yorkshire extends Dog {
	
   @Override
   public void bark(){
   		sout("와우와우!");
   }
}

 

 

 

Object 형변환 

- 객체간의 형변환은 필수다 ! (배열) 

- 원칙 : 부모 클래스의 데이터 타입이 자식 클래스보다 크다 ==> 상속 관계 

 

List<String> list = new ArrayList<>();

 

Video movie = new Movie();
Video drama = new Drama(); 


Video[] videos = { new Movie(), new Drama(), new Sport() } 

for ( Video video : videos) {
	video.watch();
}

 

- 단, 부모형으로 변환시에는 제약이 있다 ! 자신만이 가지고 있던 메서드는 사용 불가 

- 부모 -> 자식으로 형 변환시 반드시 강제 캐스팅 필요 ! 

 

- 자식 obj = (자식) 부모형 객체 

 

- if (obj instance of 변환하고자 하는 타입) => 

 


모든 새로운 기술이 나오면 게시판을 짜본다. 

 

짜봐야 안다 ! 

 

 


 

과제 : phoneInfo 예제 v2 

1.일반 2.동창 3.직장 

 

-> General

-> University

-> Company

 

-> Contact를 하나로 관리한다고 할 때 얘네 타입을 일치하여 관리하는 방법이 어떻게 가능할까? 

=> 다형성 ! 

 


상속을 이용한 contact 프로그램 리팩토링 ! 

 

public void addInfo() {

    String type = InputView.getType();
    String name = InputView.getName(ADDITION);
    String number = InputView.getNumber();
    LocalDate localDate = LocalDate.of(InputView.getDobYear(), InputView.getDobMonth(), InputView.getDobDate());

    switch (type) {
        case "일반" -> contacts.add(new ContactGeneral(type, name, number, localDate));
        case "동창" -> contacts.add(new ContactUniversity(type, name, number, localDate));
    }
}

 

함수형 인터페이스를 이용한 print 메서드 분리 (전략 패턴 구현) 

 

package kosta.mission2.mission2_07.ui.printAction;

public interface PrintAction {
    void print();
}

 

 

package kosta.mission2.mission2_07.ui.printAction;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class PrintGeneralContact implements PrintAction{

    private String type;
    private String name;
    private String number;
    private String dobFormatted;

    public PrintGeneralContact() {
    }

    public PrintGeneralContact(String type, String name, String number, LocalDate dob) {
        this.type = type;
        this.name = name;
        this.number = number;
        this.dobFormatted = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일").format(dob);
    }

    @Override
    public void print() {
        System.out.printf("\n[%s] 이름: %s 전화번호: %s 생년월일: %s\n", type, name, number, dobFormatted);
    }

}

 

package kosta.mission2.mission2_07.ui.printAction;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class PrintUniversityContact implements PrintAction{

    private String type;
    private String name;
    private String number;
    private String dobFormatted;

    private String major;
    private String studentId;

    public PrintUniversityContact(String type, String name, String number, LocalDate dob, String major, String studentId) {
        this.type = type;
        this.name = name;
        this.number = number;
        this.dobFormatted = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일").format(dob);
        this.major = major;
        this.studentId = studentId;
    }

    @Override
    public void print() {
        System.out.printf("\n[%s %s %s] 이름: %s 전화번호: %s 생년월일: %s\n", type, major, studentId, name, number, dobFormatted);
    }
}

 

 

 

 

 

 


abstract 클래스를 알아보자 ! 

 

인스턴스화를 금지하는 abstract => 객체화가 불가하다. 

 

추상 메서드의 목적 => 자식에게 반드시 overriding을 통해 구현을 강제한다 ! 

 

public abstract class Account{
	add();
}

 

추상 클래스를 인스턴스화하면 에러가 발생한다 ! 

 

Account obj = new Account("111", "lee");

=> 에러 

 

 


그런데 왜 추상클래스는 구체적인 구현을 금지할까? 

 

추상클래스니까... ? 

 

객체 생성 목적이 아니라 자식 클래스의 구현을 위해 존재한다. 

 


 

추상 클래스를 구현해보자 

 

package kosta.basic.day014.oop2;

public abstract class Role {
    abstract void doSomething();
}

 

다음과 같은 다형성이 가능하다.

 

Person person1 = new Person("홍길동", new Study());
person1.doSomething();

Person person2 = new Person("홍길동", new Study());
person2.doSomething();

 

그런데 그냥 일반 상속을 사용해도 가능하다. 

 

왜 ? 

 

강제하도록 하기 위해서. 

 

코드의 일관성 => 반드시 해당 메서드가 구현될 것이며, 설계로서 존재한다는 것이 보장된다. 

 

코드의 독립성 => 한 클래스를 수정할 때 다른 코드가 바뀌지 않는다. 

 

인터페이스와 추상클래스를 사용하는 이유 ! 

 


인터페이스 

 

인터페이스가 왜 나왔을까? 

자바에서 다중 상속을 허용하지 않기 때문 

 

사용 용도

1. 자신이 인터페이스를 생성해서 사용하는 경우

2. 자바 API 인터페이스를 사용하는 경우 

 

-> 추상클래스와 용도가 같다

-> 모두 추상 메서드 => abstract를 붙여도 되고 안 붙여도 된다. 

 

인터페이스로 형변환이 가능하다 ! 

 

role을 인터페이스로도 구현하기 

 

package kosta.basic.day014.oop2.abstractEx2;

public interface RoleInterface {
    void doSomething();
}

 

자바 api에서 쓰는 interface는 기능을 구현하기 위해 사용한다 ! 

package kosta.mission2.mission2_11.interfaceExample2;

public class MyThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i< 10; i++){
            try{
                Thread.sleep(1000);
            } catch (Exception e){
                System.out.println(i);
            }
        }
    }

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread = new Thread(myThread);
        thread.start();

        for (int i = 11; i<=20; i++){
            try {
                Thread.sleep(1000);
            } catch (Exception e){
                System.out.println(i);
            }
        }
    }
}

 

 


인터페이스 wrap up 

 

- 자바의 다중 상속 제약에 따른 대안 - 필요 

- implements => 구현한다 (overriding을 통한 추상 메서드 구현) 

- 직접 인터페이스를 생성하는 경우 -> 코드의 독립성, 일관성을 추구 

- Java API 인터페이스를 사용 -> 특정한 고유 기능을 구현하기 위함 

- 인터페이스로 형변환 가능하다 ! => 자바의 다형성 표현 

 

 

 

추상클래스 vs 인터페이스  !

 

존재 목적 부터 다르다! 추상 클래스는 그 클래스를 상속 받아 확장하는 것, 인터페이스는 껍데기만 있는 클래스의 설계를 강제적으로 구현하도록 하는 것.

 

공통점 

- 추상 메서드를 갖고 있다 : 직접 구현이 아닌 extends와 implements를 통한 하위 객체 구현의 설계 방식을 제공

- 하위 객체 구현을 강제함 

 

차이점 

- 추상클래스는 상속의 방식을 이용하므로 상위 객체의 필드와 기능을 공통으로 소유함 

- 클래스/인터페이스

- 추상클래스는 다중 상속이 불가능하며, 인터페이스는 다중 구현이 가능함 

- 추상클래스는 메서드 명에 abstract를 필수적으로 붙여야 함. 인터페이스는 필수가 아님. 

 

 


 

 

 

반응형