기초단계/JAVA

2023.02.27 Java복습

춘핑이 2023. 2. 27. 18:32

객체지향

21. 메소드 동적 바인딩

함수 호출 위치 결정 방식 이해하기
호출되는 함수의 위치 결정 문제
참조 형식이 Exam인데 어떻게 우선순위가 높아지는 것이지? 다른 자식객체의 메소드가 호출이 되는지?

부모와 자식에 각각 total메소드가 있다고 해보자.

public static void print(Exam exam){
    int total = exam.total();
}

일때 어떤 total을 불러오냐? 전달된 객체에 따라 달라진다.

c++의 경우
참조형식에 의한 결정 : 정적 바인딩 컴파일 시점에 결정되어있다.

자바는 실행중에 결정이된다 이것을 동적 바인딩이라고 한다.
jump할 위치를 정하지 않는다.
자바는 클래스가 2개가 잇으면 메소드의 목록을 테이블로 준비해둔다.
함수마다 각자 번지를 가지고 있다.
객체 전달시점에 어느 번지로 갈지 전달하고 결정한다.

이때 들어가는 객체가 어떤 함수 테이블을 가져갈건지 가지고 간다.
객체들이 데이터를 담는 공간외에 1바이트를 확장해서 자기의 메소드 테이블을 가리키는 참조주소를 포함하게된다.

그래서 자기 함수테이블에 대한 객체 번지를 추가로 가지고 간다.
따라서 객체에 따라 달라지는 이유는 객체가 알아서 가지고 가기 때문에 달라진다.

22. 코드 집중화와 추상화

객체지향 방법론에서 끝에 있는 부분이다.

22.1 코드 집중화

코드 집중화는 중요하다.
프로그램을 만들때 a프로그램에서 사용하는 일부 b프로그램에서 사용하는 일부가 다 똑같다면?
다 따로 놓는 것 보다 집중화로 모아놓고 사용하는 것이 좋다.
직접구현하는 것이 아닌 이것을 호출하는 관계로 사용하는게 좋다.
이것은 재사용이 아니라 집중화이다. 집중화와 재사용은 다르다.
이전 제품이라면 재사용이지만 이전 제품이아니라 같은 제품을 만드는데 모아놓고 만드는 것이니 집중화이다.
처음만들때는 복붙하고 이후에 집중화 추상화 캡슐화 등을 한다.
고도화작업 리팩토링 등이라고 한다.

22.2 추상화

프로그램은 객체 지향이고 캡슐의 단우로 나누어져 잇다.
서비스가 같은 것일 경우 기능을 모아 놓는 것이 추상화이다.
단순 코드 집중화이 아니라 -> 서비스 집중화(캡슐단위의 공통서비스)라고 한다.
캡슐단위 공통기능의 집중화를 의미한다. 공통역할을 가지고 있기 때문이다.
공통단위를 모아놓고 is a 상속을 하면 구현할필요가 없어진다.
이런 공통화된 클래스, 공통분모화된 클래스를 원래 만드려던 것이 아니라 공통분모로서 나온 것으로 '추상클래스'라고 한다.

장점
1.코드집중화 반복되는 코드를 몰아 넣엇때문
2.일괄처리
일괄적으로 관리를 할 수 있다.
여러 것들을 한번에 담으려고 할때
원래는 한번에 담을 수있는 자료형이 없어서 각각 마련해야한다.
추상클래스로 같은 그릇에 담을 수 있다.
즉 추상클래스가 부모이기때문에 하나로 참조시킬 수가 있다.

추상클래스로 만드는 두가지 상황 #2
성적관리라고 햇을때? 계속 추가하는데 공통분모가 있으니 만들기 쉽다.
공통분모를 추상클래스라고 한다. 추상클래스가 진짜 추상이되려면 추상클래스만 되어야하고 이게 추상화이다.

23. 추상 클래스 만들기 추상화

Exam클래스를 추상화 할 것이다.
추상화는 공통분모화라고 할수있고 추상클래스는 공통클래스라고 할 수 있다.
역할에 대한 집중화라고 할 수 있다.
완전하게 공통분모로만 사용이 되느냐? 하나로만 만들면되냐 확장해서 사용할수잇느냐?
공통분모이지만 자체로서도 완전한 클래스로 사용되면 추상화할 필요가 없다.
공통분모로만 뼈대로만 사용한다면 추상화를 해야한다. 뼈대가 실체화 되지 않도록 해야한다.

뼈대로 만들기1
Exam이 뼈대로만 사용할 수 있도록 만든다 즉 객체화되는 것을 막는다.
new Exam()을 불가능하게 하기 위해 클래스에 abstract를 붙이면된다.
이러면 직접 생성을 할수 없게 된다.
total()/ avg()등을 빼야한다.

24. 추상 메소드(Abstract Method)

그림판 프로그램을 만든다고 해보자
각 도형마다 기능을 나누어잇다면 각 도형마다 배열을 따로 만들어야한다.
추상화를 하면 하나의 배열로 다받을 수잇다. 공통된 부분을 모으면 집중화 할 수있다.
그런데 paint()의 경우 각자 구현방식이 달라서 오류가 난다.
그래서 shape에 서비스의 정의만 가지게 하면된다.
이것이 뼈대메소드 즉 추상 메소드가 된다.
각자 override하면 실제 객체를 부를때 알아서 사용하게 된다.

추상클래스용도는 두가지이다.
1.공통분모 자료형만들때
2.공통분모로서 다음 버전을 위한 재사용 용도

Exam은 다음버전을 만들기 위한 재사용모듈이다.
추상화 메소드란? 공통으로 제공되어야할 서비스이다.
ExamConsloe이 호출할때 실제 호출하는 것은 구현된 객체들이다.

25. 추상 메소드(Abstract Method) 구현하기

뼈대로 만들기2
공통기능인데 내가 구현할 수 없는 상황 -> 그것을 자식이 책임지도록 만든다.
구현은 공통이 아니고 기능이 같은 것이고 공통자로형으로서 의미가 잇다면 추상메소드로 둬야한다.

public abstract int total();

public abstract float avg();

@Override
public int total() {
    return getKor() + getEng() + getMath() + com;
}

@Override
public float avg() {
    return total() / 4.0f;
}

26. 팩토리 메소드(Factory Method)

추상메소드가 생각보다 많이 사용된다. 자체로 쓰이는 것보단 패턴으로 사용된다.
추상화를 한다는 것은 공통화작업을 하는것이다. 공통구현부분들을 모아두는 작업이다.
total이나 avg처럼 공통이아닌데 공통으로 올려둔 이유는 공통 자료형이라는 것이다.
일괄 서비스에 들어가는게 분명하다면 구현은 공통이 아니더라도 들어가는게 맞아서 구현을 했다.

그런데 여기서 문제를 만난다.
또다른 클래스 ExamConsole에서 Exam의 기능을 사용하고 있다.
input print에서 exam기능을 사용한다.
Exam을 공통분모화했기 때문에 오류가 난다. 그대로 사용할 수없다.
exam형태의 클래스를 가지고 만들어야한다. newlec을 만들때 examconslole의 소스코드를 가져와서만든다.
소스코드를 만드는게 아니라 binary를 만들어서 교체하는 방법을 찾기
후자가 더 바람직한 방법이다.
이걸 해결하기 위해 같은 방법이 나왓고 이방법을 반복해서 사용하게 되었다.
이것을 매번 쓰는 패턴이라고 디자인패턴이다. 어떻게 바꿔치기 할것인가?

부모를 추상으로 만들고 객체 생성하는 부분을 자식이 책임질수잇도록만드는것이 팩토리 메소드이다.
추상메소드를 만들고 추상메소드를 불러오게 하는 것이다.
이런형태의 패턴을 썻는데 인터페이스 사용하면 굳이 이럴 필요가 없긴하다.

27. 팩토리 메소드 구현하기

newlecExamConsole을 만들것이다.

public class newlecExamConsole extends ExamConsole {
    @Override
    protected Exam makeExam() {
        return new NewlecExam();
    }
}

Exam exam = makeExam();
exam.setKor(kor);
exam.setEng(eng);
exam.setMath(math);