[JAVA]객체지향(8) : 인터페이스

ho's·2022년 4월 16일
0
post-thumbnail
post-custom-banner

위 글은 김성박선생님의 자바 강의를 바탕으로 쓰여졌습니다.
더 자세한 내용은 아래 링크를 통해 알아보실 수 있습니다.

부부개발단 유투브


인터페이스

  • "무슨 기능을 만들어야 할까?" VS "구현부터 하기"
  • 어떤 기능을 만들어야 할지부터 고민한다. 만들어야 할 기능들을 관련된 것끼리 묶은 후 이름을 지어준다.

인터페이스 작성 문법

[public] interface 인터페이스이름 {... }
// 예시
public interface User { ... }

  • "인터페이스이름"은 Upper CamelCase로 작성된다.

  • interface도 확장자가 .java파일로 작성한다.

  • 인터페이스의 모든 필드는 public static final이어야 하며, 모든 메소드는 public abstract 이어야 한다.(JAVA 7까지는) final, abstract를 생략하면 자동으로 붙는다.

    -Java 8부터는 디폴트(default)메서드와 정적(static)메서드도 선언이 가능하다.

LottoMachine 인터페이스를 만들어 보자.

LottoMachine은 위와 같은 기능이 필요하다.

  1. 1~45까지 써있는 Ball을 로또 기계에 넣는다.
  2. 로또 기계에 있는 Ball들을 섞는다.
  3. 섞인 Ball중에서 6개를 꺼낸다.

public void setBalls(Ball[] balls);

위 코드의 setBalls메소드는 외부로 부터 45개의 balls를 받아들이는 기능을 한다.

LottoMachine의 메소드들을 보면 구현하는 코드가 없다는 것을 알 수 있다. 즉, 인터페이스의 메소드는 모두 추상메소드라는 것이다.

사실 abstract를 써줘야 하지만, 인터페이스의 메소드는 모두 추상메소드이기 때문에 생략이 가능하다.

인터페이스가 가지는 모든 필드는 public static 하다.

위의 그림에서

int MAX_BALL_COUNT = 45;
int RETURN_BALL_COUNT = 6;

에는 생략된 코드가 있고 다음과 같다.

public static int MAX_BALL_COUNT = 45;
public static int RETURN_BALL_COUNT = 6;

인터페이스에서 생략가능 한 것

  1. 인터페이스의 모든 메소드는 추상메소드이기 때문에 abstract가 생략 가능하다.
  2. 인터페이스의 모든 필드들은 public static이기 때문에 생략 가능하다.

LottoMachine 인터페이스를 사용해보자!

1. 인터페이스를 사용하는 LottoMachineImpl 클래스를 만들고, 인터페이스를 구현한다. LottoMachine에 정의된 메소드들을 오버라이딩했지만, 메소드의 내용은 비어있다.

2. LottoMachine을 실행시킬 LottoMachineMain 클래스를 만들자.

3. Ball 클래스에서 받아들일 공을 설정하자.

Ball은 만들어졌을때의 숫자가 변하면 안되는 특징을 가져야 한다.
여기서 우리는 불변클래스(Immutable Class)를 이용해서 클래스를 만들어야 한다.

1) Ball의 생성자를 만들어 준다.
2) number의 접근제어자가 private이기 때문에 내부적으로만 사용가능하다.
3) 외부적으로 알려주기 위해서 getNumber() 메소드를 만들어, 자신의 number를 return해 준다.

이제 Ball을 만들어보자!!

로또 번호가 45개까지 있으니, 우리는 45개의 객체를 만들어야 한다.
반복문을 이용하자.

lottoMachine객체를 이용해서 실행시키는 코드를 작성해보자.

하지만 실행시키면,

위와 같은 결과를 얻는다.
그 이유는 메소드를 구현하지 않았기 때문이다.

LottoMachineImpl의 메소드들을 채워보자.

  package totojava.com.example.util2;
public class LottoMachineImpl implements LottoMachine{

private Ball[] balls;

    @Override
    public void setBalls(Ball[] balls) {
        this.balls = balls;
    }
    //Math.random() ==> 0.0 <= x < 1.0
    //                  0.0 <= x < 45;
    //                 (int) 0 <= x < 45;
    @Override
    public void mix() {
        for(int i =0; i<10000;i++){
            int x1 = (int)(Math.random()*45);
            int x2 = (int)(Math.random()*45);
            if(x1 != x2){
                Ball tmp = balls[x1];
                balls[x1] = balls[x2];
                balls[x2] = tmp;
            }
        }
    }

    @Override
    public Ball[] getBalls() {
        Ball[] result = new Ball[6];
        for(int i=0;i<6;i++){
            result[i] = balls[i];
        }
        return result;
    	}
    }

mix()메소드

0~44까지 랜덤으로 얻은 x1,x2가 같지 않은 경우, balls[x1]과 balls[x2]의 값을 바꾸어 주는것이다. 이러한 작업을 10000번 반복하면, balls[] 배열의 값들은 잘 섞이게 될 것이다.

getBalls()메소드

Ball[] 배열을 return값으로 받게 만들었다.
Ball[] 배열의 앞의 6개의 값(Ball[0],Ball[1],...,Ball[5])을 새로운 배열 (result[0],result[1],...,result[5])에 담는다.
그리고 result를 반환해 준다.

정해진 숫자를 인터페이스에서 정의된 변수명으로 바꾸어준다면 더 유연한 코드가 될 수 있다.

인터페이스의 default method(JDK 8에 추가된 메소드)

  • A라는 사용자가 메소드가 3개 선언된 interface를 작성한 후 외부에 공개를 하였다.(라이브러리로 제공)
  • 여러 사용자들이 해당 인터페이스를 이용해 구현하였다.
  • A라는 사용자는 인터페이스에 1개의 메소드가 추가로 더 있는게 좋다고 판단했다.
    그래서 메소드를 추가했다.
  • 여러 사용자들은 라이브러리가 업데이트 된 줄 알고 업데이트했다. 무슨일이 벌어질까?

인터페이스의 static method(JDK 8에 추가된 메소드)

  • 인터페이스를 구현한 클래스가 없어도 사용 가능한 static method

싱글턴 패턴

  • 객체 생성과 관련된 패턴
  • private 생성자
  • private한 자기 자신을 참조하는 static 필드
  • public static한 자기 자신을 참조하는 static필드를 반환하는 메소드

예제를 통해 알아보는 singleton


위의 코드는 BeanFactory객체를 6개 만든다.

BeanFactory인스턴스를 하나만 만들고 싶다.

규칙을 지켜라!!

  1. private한 생성자를 만든다.
  2. 자기 자신 인스턴스를 참조하는 static한 필드를 선언한다.
  3. 2번에서 생성한 인스턴스를 반환하는 static한 메소드를 만든다.


싱글턴은 메모리상에 인스턴스를 하나만 올리는것!
방법은 익숙해 질때까지 반복해 보도록 하자

profile
그래야만 한다
post-custom-banner

0개의 댓글