Java 객체지향

29. 코드 분리와 인터페이스

추상클래스는 집중화이다.
인터페이스는 무엇을 하나? 분리이다. 코드 분리를 위해 어쩔수 없이 나오는 것이다.
인터페이스는 두가지의 형태를 가지고 있다.
인터페이스는 무엇입니까? 어떤곳 어떤장소 어떤시간을 접근할때 일반적인 방법으로 접근을 못할때 접근할 수 있게 해주는 도구가 인터페이스이다.
분리되있는 상대를 만날수 있는 접점이 인터페이스고 자바, 소프트웨어에서도 이게 필요하다.

인터페이스가 필요한가?
핸드폰 만들때 배터리를 분리형으로 만들가 일체형으로 만들까?
그냥 떼어내는 것이아니라 연결하기위한 도구가 필요하다.

분리하는 이유
1.배터리는 다른 업체들이 만들수있게 할까?
2.배터리를 교체형으로 만들까?
3.폰은 다양하지만 배터리를 표준으로 만들까?
4.모둘별로 별도 업데이트할까?
등등 의 이유가 있다.
분리햇다가 낄때 아무런 약속없이 꽃을 수 없다.
이 약속이 인터페이스 이다. 이걸 어떻게 구현할 것인가?

반드시 이것만큼은 서비스 목록으로 가져야한다

interface Battery{
 int getEnergy();
 boolean checkVolt();
}

앞으로 꽃아질 배터리를 위한 간접도구이다.
나중에 setBattery로 객체를 꽃아 넣을 것임.
프로그램에선 일단 구현되지도 않은 것을 호출하는 것이다.
이 방식대로라면 일단 프로그램은 되지만 구현한 배터리가 있다면 프로그램이 실행되게 될 것이다.

실제적인 구현체는 구현하겟다고 implements인터페이스 상속을 해주면 된다.

분리된 객체를 사용할수잇게해주는 약속이다.

일상에서 사용하는 용어임을 기억하고 자바에서도 그렇게 생각해보자.

인터페이스는 두가지 종류가있다.
1.부품이 분리되는 인터페이스
여러개 메소드가 있고 부품이 가지고잇는걸 구현하는 것처럼 생김
2.부품이 아니라 코드의 일부분만 분리
메소드에서 일부분만 분리할때 사용한다.

30. 추상클래스와 인터페이스의 차이

공통분모 : 추상클래스? 인터페이스?
개체들의 공통분모를 일반화한 이름
공통화 일반화하는것이 추상화작업이고 그것이 추상클래스이다.
공통으로 잇다면 집중화할 수 있다. 기능적으로 같이 가지고 있어야할 서비스가 있다면 집중화하거나 강제화할 수 있다.
집중하겠다는 것이 첫번째 목표이다.
공통분모를 쓰겟다하면 밑에 있는 것을 아무거나 다쓸수있다.

인터페이스는 이것과다르다. 추상클래스는 나중에 집중화를 통해 만들어지지만
인터페이스는 일단 정의 해두고 구현하지 않고 꽃아넣는다. 기능이 필요하다면 구현해서 꽃아넣어달라고 하는 것이다.
다만 서비스 받고 싶다. 다만 기능이 필요할 경우 공통된 것들이 없어도 꽃아 넣을 수 있는 것이다.
사진참조
인터페이스에서 필요로하는 것이 구현만 하면 넣을 수있는것이다.
인터페이스에서 주가 되는 것은 서비스를 부르는 클라이언트이다.
a기능을 하다가 b기능이 있다면 여러개 잇다면 그냥 꽃아서 사용을 할 수도 있다.

class상속은 유전자를 상속받는거라면 인터페이스 상속은 사교적으로 필요할때 가는 것이라고 생각하면 쉽다.

31. 객체 단위로 분리/결합을 위한 인터페이스 구현하기

중간의 코드가 대체 되거나 없어질경우에 중간에 캡슐로 인터페이스를 꽃으면 없어져도 프로그램이 돌아가게 된다.
더작은 단위로 인터페이스가 잇는 경우가 있다. 일부 기능만 대체 될 경우 만들어지기 위해 기다리고 마무리 져야하나?
인터페이스로 처리하고 일단 일하는게 맞다
구현코드의 일부가 그거라면 그부분도 인터페이스를 사용할 수 있다.

교체되거나 만들어지지않앗을때 대안으로 사용할 수 있는것이다.
기업에선 가장 기본이 된다.

용어를 이해하고 어떻게 활용되는지는 현재는 이해하지 못한다. 앱 만들면서감을 살리는게 맞다

초간단 예제를 만들어보았다.

public class Program {
    public static void main(String[] args) {
        A a = new A();
        a.print();
    }
}

public class A {
    private B b;

    public A() {
        b = new B();
    }

    public void print() {
        int total = b.total();
        System.out.println(total);
    }
}

public class B {

    public int total() {
        return 30;
    }
}

현재 이코드들은 결합력이 매우 강하게 이어져잇다. 한쪽 소스코드가 오류가나면 여기저기 다 고쳐야할 것이다.
소스코드를 통하지 않고 서로를 바꿀 수 있도로고 하는것이 인터페이스이다.

32. 개체 결합을 위한 인터페이스 구현하기

객체 결합력을 낮추는 코드로 변경해보자.
A와 B가 부품으로 사용함으로써 결합력이 강하다.
B가 없더래도 A가 만들어질 수 있도록 해야한다.

A - 인터페이스 - B의 순서를 가지게 하자.
기능적인 것만 구현이 되엇다면 바꿔낄 수가 있다.
다양한 형질을 만들 수있어서 다형성이라고 한다.
사용하는 사람은 B를 볼 수 없다. B를 바꾸려면 A를 통채로 바꿔야 한다.

A가 생성할수있는 객체가 없다라고 생각해보자 이걸 대신할 수있는게 인터페이스이다.

인터페이스는 구현하게 아니기때문에 생성자에서 생성할 수 없다.
인터페이스를 가지고 참조라는 것을 가능하게 해야한다. 구현한객체라면 무조건 참조가 가능하게 한다.
그 객체가 포탈을 사용할 수 있게 해준다.

public interface X {
    int total();

}

public class B implements X {

    @Override
    public int total() {
        return 30;
    }

}

public class A {
    private X x;


    public void setX(X x) {
        this.x = x;
    }

    public A() {
    }

    public void print() {
        int total = x.total();
        System.out.println(total);
    }
}

  public class Program {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        a.setX(b);

        a.print();
    }

}

원래는 a와 b가 일체형이엇는데 program에서 set을 통해 결합이 되엇다. 이 결합이 인터페이스를 이용하면 누구든지 결합이 될 수있다.
X인터페이스를 구현한다면 어떤 클래스이던 사용할 수 있다.
그런데 소스코드 없이 B를 만들지 않고 바꿔야한다.
새로운 클래스로 추가햇을 경우 바꾸는 방법을 다음강의에서 알아보자.

33. 새로운 객체로 바꾸기(문자열을 읽어서 객체로 만들기)

B객체를 만들어서 꽃아넣어는데 소스코드를 고쳐야만 바꿀 수 있다.
그런데 소스코드를 자꾸 고치는건 말이 안된다.
B클래스를 사용 C클래스사용 -> 설정파일로 빼서 하기 XML형태와 어노테이션
스프링이 DI를 도와준다.

외부파일의 에서 파일을 불러오고 경로가 문자로 온다.
이 경로의 주소를 통해 Class clazz = Class.forName(className);클래스 명을 가져온다.
그리고 이정보로 instacance를 얻을 수 있다.

public class Program {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("src/ch03객체지향/sec06인터페이스/setting.txt");
        Scanner sc = new Scanner(fis);
        String className = sc.nextLine();
        sc.close();
        fis.close();

        Class clazz = Class.forName(className);

        A a = new A();
        X x = (X) clazz.newInstance();
        a.setX(x);

        a.print();
    }
}

원래대로라면 xml로 정보를 얻어오는 것이다. 요즘에는 스프링으로 설정을 가져온다.

34. 일부 기능을 분리하는 인터페이스

같은 계열의 클래스면 추상클래스로 하면되는데 완전다르다면 인터페이스로 하면된다.
개체 단위가 아니라 전체가 아닌 일부기능만 구현하려고 한다면 어떻게 해야할까? 약간의 커스터마이징
https://youtu.be/BSEdMmBXKHg

frame.addwindowLister WindowLister가 인터페이스이다.
구현화해야하는 목록이 나온다.
없어도 문제가 안됫엇는데? WindowLisnter가 옵션이엇기 때문이다.

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JOptionPane;

public class gameWindowListner implements WindowListener {

    @Override
    public void windowClosing(WindowEvent e) {
        JOptionPane.showMessageDialog(null, "GOOD BYE");
        System.exit(0);
    }


인터페이스라는 것이 일부기능에 대해서 사용자에게 당신이 만들라고 미뤄둘때도 사용할 수잇음을 알게 되었다.

35. 인터페이스를 구현하는 위치는?

구현하는 위치가 새로운 클래스로 구현했었다. 아주 정상적인 방식이다.

그런데 지난시간 예제처럼 구현만 하고 객체로서의 역할이 크지 않을때 게임프레임이 알아서 구현햇어야하는 것이다.
별도의 클래스로 객체로 증가시키는 것은 좋지않다. 부품이 많아지면 좋지않다.
조금더 효과적인 방법은 안에 만드는 것이다.

public class GameFrame extends Frame implements WindowListener {

    @Override
    public void windowClosing(WindowEvent e) {
        JOptionPane.showMessageDialog(this, "GOOD BYE");
        System.exit(0);
}

JAVA 예외처리

1. 예외처리에서 예외란 무엇을 말하는가?

예외란 오류중의 하나이다.

오류
1.구문오류 치명적이지 않음
컴파일러가 어디가 잘못된지 알려주고 고치면됨
2.논리오류 치명적임
구문오류는 전혀없는데 오류가 나는 경우 학생수가 14명인데 13명으로 평균을 내버림
구문상에는 오류가 없어서 에러는안나는데 문제가 안생겨서 찾기가 어려운경우이다.
개발자가 알고 오류를 내는게 아니다. 사용자가 사용하다가 발견하는 경우가 잇따.
가상의 사용자를 두고 오류를 잡도록 노력한다.
3.예외 누군가만 어떤 컴퓨터만 어떤 상황에서만 예외적으로 발생하는 오류
입력갑의 오류 물리적인 장치 우리가 해결할 수있는게 아니다.
하드웨어적 으로 오류가 날수도잇는데 작은 실수가 예외를 발생시킬 수도 있다.
라이브러리가 메시지를 날리고 종료하는 경우에도 예외처리가 필요하다.

이 예외를 처리해줘야한다.

2. 예외를 처리한다는 것은 무엇을 말하는 것이고 어디에서 예외를 처리해야 하는가?

성적관리 입출력을 하면서 파일을 입출력한다고 생각해보자.
하드를 인터페이스로 사용한다 이것이 API고 이녀석이 입력하거나 처리할때 권한 파일존재 파일용량등을 체크하고 없다면 책임자에게 예외를 뱉는다.
API는 보고를 통해서 이것을 만낫다는 것을 알려줌. return으로 예외를 보고하는데 사용되는건 아니고 중간에 라이브러리를 통해서 보고가 올라간다.
그래서 보고체계만 할 수 있도록 일괄적인 채널을 만들었다.
문제가 발생하는 것에 대한 식별자를 만들고 예외를 던진다. 자바는 예외의 특수한 의미의 객체를 이용한다.
throw new 권한없음예외();기능보단 식별할 수 있는 특수한의미의 클래스이다.
유지보수가 훨씬 더 쉬워진다.
try {
} catch
던지니 잡는다. 적절한 조치를 취한다. 치명적이라면 끝내버리고 치명적이지 않으면 예외메시지와 진행되도록한다.

3. 예외를 던지는 클래스 준비하기

예외를 던질 수있는 라이브러리를 만들어보자 계산기를 만들고 범위를 벗어나면 예외라고 판단하고 던지자.
먼저 계산기를 준비햇다.

public class Program {

    public static void main(String[] args) {
        Calculator calc = new Calculator();
        int result = 0;

        result = Calculator.add(0, 0);
        result = Calculator.sub(0, 0);
        result = Calculator.multi(0, 0);
        result = Calculator.div(0, 0);
    }
}

public class Calculator {
    public Calculator() {

    }

    public static int add(int x, int y) {
        return x + y;
    }

    public static int sub(int x, int y) {
        return x - y;
    }

    public static int multi(int x, int y) {
        return x * y;
    }

    public static int div(int x, int y) {
        return x / y;
    }
}

4. 예외 클래스 생성과 던지기(throw)

public static int add(int x, int y) throws 천을_넘는_예외 {
    int result = x + y;
    if (result > 1000) {
        throw new 천을_넘는_예외();
    }
    return result;
}

1000을 넘으면 예외가 발생하도록 던져버린다(throw) 던지면서 객체를 생성한다.
그런데 여기서 부터 던져진다.내가 처리하지 않고 사용자가 처리할 수 있도록 보내버린다.
자기자신이 처리하지 않겠다면

public class 천을_넘는_예외 extends Exception {

}

그런데 던지는 예외는 throws이다. 여러개의 예외를 던질 수 있기 때문이다.

public static int add(int x, int y) throws 천을_넘는_예외, 음수가되는예외 {
    int result = x + y;
    if (result > 1000) {
        throw new 천을_넘는_예외();
    }
    if( result < 0)
        throw new 음수가되는예외();
    return result;
}

사용하는 프로그램쪽에서 예외를 처리해줘야한다.
3가지 선택지가 있는데 main함수로 던져버리기 try-ctach로 하기가 있다.
메인에 던져버리면 default행동을 실행하고 프로그램이 끝나버린다.
java runtime이 이 보고를 받게 되는데 오류나면 이게 치명적인지 모르니 어떤 일을 수행할지 모르니 그이후는 아무것도 실행이 되지않는다.
이 예외를 어떻게 처리할건지 알아보도록 하자.

5. 예외를 받고 처리하기

던져진예외를 처리하는 방법을 알아보자.
예외처리는 두가지 의미가 있다.
1.예외에 대한 안내메시지를 사용자에게 안내하는것
2.치명적인지 아닌지에따라 이어갈지 말지를 정하는 것이다.
다른 api라면 확인해서 예외처리를 해주자.
일단 add가 발생하는 것을 알고 있으니 처리해주자.

try {
    result = Calculator.add(0, 0);
} catch (천을_넘는_예외 e) {
    System.out.println("1000을 넘는 예외가 발생하였습니다.");
}

커스텀해서 예외마다 처리 설정을 달아줄수있다.
예외를 만드는 입장에서 동일하게 예외 메시지를 주고 싶다면

public class 천을_넘는_예외 extends Exception {
    @Override
    public String getMessage() {
        return "1000을 넘는 예외가 발생하였습니다.";
    }
}

프로그램만들대 일관되게 나오게 할 수 있다.

try {
    result = Calculator.add(0, 0);
} catch (천을_넘는_예외 e) {
    System.out.println(e.getMessage());
}

이것을 출력하게 되면 예외메시지를 받을 수 있다.

6. 다중 예외처리

예외가 여러개일때 어떻게 특화시킬 수 있을까?
감싸는 try블럭에 catch절을 둘것이냐 해서 여러개 catch절을 할건지 기존catch절에서 한번에 처리할건지 결정할 수 있다.
두개의 예외가 동일한 처리라면 같이해도된다. 개별적인 예외라면 따로 하자.
try중첩도 할 수 있다.

sub()에서도 같은 예외가 있다면 같은 try문에 넣어서 예외처리를 할 수 있다.

try {
    result = Calculator.add(0, 0);
    System.out.println(result);
    result = Calculator.sub(0, 0);
    System.out.println(result);
} catch (천을_넘는_예외 e) {
    System.out.println(e.getMessage());
} catch (음수가되는예외 e) {
    System.out.println(e.getMessage());
}

하나만 특화시키고 나머지는 일괄처리 하고싶다면?
모든 예외가 가지고 있는 부모가 있다.

catch (Exception e) {
    e.printStackTrace();
}

이렇게하면 나머지를 한번에 일괄적으로 처리를 할 수있다.
얘는 모든 예외의 부모이기때문에 위로 올라가면 안된다.
catch가 순차적으로 가기때문이다.
만약 모든 예외에서 같은 게 나온다면? 비효율적이다. finally를 해주면 무조건 꼭들리는 곳이다.
집중해야한다면 finally에 넣어서 일괄처리하자.

try {
    result = Calculator.add(0, 0);
    System.out.println(result);
    result = Calculator.sub(0, 0);
    System.out.println(result);
} catch (천을_넘는_예외 e) {
    System.out.println("특화처리");
} catch (음수가되는예외 e) {
}  catch (Exception e) {
} finally {
    System.out.println("입력값에 오류가 있습니다.");
}

7. UnChecked 예외

예외는 두가지 예외가 있다. 꼭잡아야하는 예외 안잡아도되는 예외가잇다
말을 바꿔서하면 Checked예외 / UnChecked예외이다.
만약 나누기에서 y가 0이라면 또 다른 예외가 된다. 이런예외가 바로 Unchcked예외이다.
모든 예외를 다 처리하면 코드가 복잡해질 것이다. 피할 수 있는 것은 알아서 피하는게 나을 수 있다.
체크할필요가 없어서 예외를 몰랏다. 도의적으로 알아서 잘 하게 하고 싶다면? 그렇게 만들 수 있다.

public class 천을_넘는_예외 extends RuntimeException {
    @Override
    public String getMessage() {
        return "1000을 넘는 예외가 발생하였습니다.";
    }
}

컴파일 타임에 잡지 말고 RuntimeException으로 만들어서 알아서 하게 두는 것이다.
혹시 사용자가 잘못된 입력을 할 수 있다고 생각하면 try-catch하면된다.
강제화할필요가 없다 생각하면 실행시에 오류가 나도록 하면된다.

'기초단계 > JAVA' 카테고리의 다른 글

2023.02.16-1 Java 복습  (0) 2023.02.16
2023.02.15-2 Java 복습  (0) 2023.02.15
2023.02.14 Java 복습  (0) 2023.02.14
2023.02.13 Java 복습  (0) 2023.02.13
2023.02.12 Java 복습  (0) 2023.02.13

+ Recent posts