-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[모던 자바 인 액션] 7주차 #9
Comments
디폴트 메서드자바 8부터 인터페이스에 메서드 구현을 포함시킬 수 있다. 이때 인터페이스에 구현하는 메서드를 디폴트 메서드라고 한다. 인터페이스를 구현하는 클래스에서는 메서드를 모두 구현해야하기 때문에 인터페이스에 메서드를 추가할때 문제가 발생한다. 메서드 하나를 추가하려면 해당 인터페이스를 구현하는 모든 클래스에서는 해당 메서드를 모두 구현해줘야 하는 것이다. 디폴트 메서드를 이용하면 인터페이스의 기본 구현을 그대로 상속하므로 인터페이스에 자유롭게 새로운 메서드를 추가할 수 있게 된다. 이로인해 호환성을 유지하면서 API를 바꿀 수 있다. 디폴트 메서드 활용패턴선택형 메서드인터페이스에는 포함되지만 실제로는 사용하지 않을 메서드가 있다면, 그 인터페이스를 구현하는 클래스에서는 사용여부에 상관없이 클래스를 필수적으로 구현주어야한다. 아마 이런 상황이라면 비어있는 메서드를 구현할 것이다. public interface MyInterface {
void usedFunction();
void unUsedFunction();
...
} public class MyClass implements MyInterface {
@Override
public void usedFunction() {
...
...
로직을 구현한다
}
@Override
public void unUsedFunction() {
구현하지 않은채로 놔둔다(빈 구현)
}
} 하지만 디폴트 메서드를 사용한다면 사용하지 않는 메서드는 굳이 빈 구현으로 구현할 필요가 없다. 실제로 자바8의 Iterator 인터페이스의 remove 가 디폴트 메서드로 정의되어 있다. Iterator 인터페이스를 보면 remove란 디폴드 메서드를 찾을 수 있다. public interface Iterator<E> {
...
default void remove() {
throw new UnsupportedOperationException("remove");
}
...
} 이 메서드는 사용자들이 잘 사용하지 않아 Java8 이전에는 remove 기능을 무시했다. 결과적으로 Iterator를 구현하는 많은 클래스에서는 remove에 빈 구현을 제공했다. 간단히 말해 사용하지 않는 메서드를 디폴트 메서드로 구현해 사용하지 않는 클래스에서는 구현을 할 필요가 없어져 불필요한 코드를 줄일수 있다. 동작 다중 상속
기능이 중복되지 않는 최소의 인터페이스우리가 만드는 게임에 다양한 특성을 갖는 여러 모양을 정의한다고 가정하자. 어떤 모양은 회전할 수 없지만 크기는 조절할 수 있다. 어떤 모양은 회전할 수 잇으며 움직일 수 있지만 크기를 조절할 수 있다. 어떤 모양은 회전할 수 있으며 움직일 수 있지만 크기는 조절할 수 없다. 최대한 기존 코드를 재사용해서 이 기능을 구현하려면 어떻게 해야 할까? public interface Rotatable {
void setRotationAngle(int angleInDegrees);
int getRotationAngle();
default void rotateBy(int angleInDegrees) { //디폴트 메서드
setRotationAngle((getRotationAngle() + angleInDegrees) % 360);
}
} public interface Moveable {
int getX();
int getY();
void setX(int x);
void setY(int y);
default void moveHorizontally(int distance) {
setX(getX() + distance);
}
default void moveVertically(int distance) {
setY(getY() + distance);
}
} public interface Resizable {
int getWidth();
int getHeight();
void setWidth(int width);
void setHeight(int height);
void setAbsoluteSize(int width, int height);
default void setRelativeSize(int wFactor, int hFactor) {
setAbsoluteSize(getWidth() / wFactor, getHeight() / hFactor);
}
} 인터페이스 조합이제 이들 인터페이스를 조합해서 다양한 클래스를 구현할 수 있다. 예를 들어 움직일 수 있고, 회전할 수 있으며 크기를 조절할 수있는 괴물 클래스를 구현할 수 있다. public class Monster implements Rotatable, Moveable, Resizable {
... 디폴트 메서드는 구현할 필요가 없다.
} 해당 클래스는 아래와 같이 호출할 수 있다. Monster m = new Monster();
m.rotateBy(180);
m.moveVertically(10); 또 다르게 이번에는 움직일 수 있으며, 회전할 수 있지만, 크기는 조절할 수 없는 Sun 클래스를 정의한다. public class Sun implements Moveable, Rotatable {
} |
Java 인터페이스 사용 규칙Java 7 이전 : 인터페이스를 구현하는 클래스는 인터페이스에서 정의하는 모든 메서드 구현을 제공하거나 슈퍼클래스의 구현을 상속받아야 함.
Java 8 이후 : 기본 구현을 포함하는 인터페이스를 정의하여 하위 호환성을 유지할 수 있음.
정적 메서드(static method)기본 구현을 포함 호출 방법 : 정적 메서드를 인터페이스에 넣으면서 관련 로직을 하나로 모을 수 있음. (객체를 선언하지 않고) 추상 클래스에서도 정적 메서드를 선언할 수 있음. 차이점은 추상 클래스는 생성자, 상태, 행동을 가질 수 있음. 디폴트 메서드(default method)기본 구현을 포함 호출 방법 : 구체 클래스에서 인터페이스의 기본 구현을 상속하므로 인터페이스에 자유롭게 메서드를 추가할 수 있음. 다중 상속 가능한 특성을 활용하여 여러 개의 인터페이스 구현이 가능함. (예시) 메서드 / 정적 메서드 / 디폴트 메서드public interface List<E> extends Collection<E> {
int size();
// List<String> names = Lists.of("Tom", "James");
static <E> List<E> of(E e1, E e2) {
return new ImmutableCollections.List12<>(e1, e2);
}
// List<String> names = new ArrayList<>();
// names.sort(...);
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
} |
스터디 날짜
2023.08.11 금 8:30-9:30
내용
챕터13. 디폴트 메서드
챕터14. 자바 모듈 시스템
공유
최승위
이성온
정민교
The text was updated successfully, but these errors were encountered: