[이것이 자바다] 8장 정리

자바 인터페이스에 대한 포스트입니다. 인터페이스와 구현 클래스, 다중 상속 등에 대한 내용이 포함되어 있습니다.
Jan 12, 2024
[이것이 자바다] 8장 정리

RemoteControl.java

package ch08; // tv 클래스와 audio 클래스의 사용법을 알려주는 것. public interface RemoteControl { int MAX_VOLUME = 10; int MIN_VOLUME = 0; void turnOn(); void turnOff(); void setVolume(int volume); void getVolume(); // 구현하는 클래스가 인스턴스를 만들었을 때 기본적으로 가지는 메소드 default void setMute(boolean mute) { if (mute) { System.out.println("무음 처리합니다."); setVolume(MIN_VOLUME); } else { System.out.println("무음 해제합니다."); } } static void chanegBattery() { System.out.println("리모콘 건전지를 교환합니다."); } }

Television.java

package ch08; public class Television implements RemoteControl{ private int volume; private int memoryVolume; @Override public void turnOn() { System.out.println("TV를 켭니다."); } @Override public void turnOff() { System.out.println("TV를 끕니다."); } @Override public void getVolume() { System.out.println(this.volume); } @Override public void setVolume(int volume) { if (volume > RemoteControl.MAX_VOLUME) { this.volume = RemoteControl.MAX_VOLUME; } else if (volume < RemoteControl.MIN_VOLUME) { this.volume = RemoteControl.MIN_VOLUME; } else { this.volume = volume; } System.out.println("현재 Audio volume: " + this.volume); } @Override public void setMute(boolean mute) { if(mute) { this.memoryVolume = this.volume; System.out.println("무음 처리합니다."); setVolume(MIN_VOLUME); }else { System.out.println("무음 해제합니다."); setVolume(this.memoryVolume); } } }

Audio.java

package ch08; public class Audio implements RemoteControl { private int volume; private int memoryVolume; @Override public void turnOn() { System.out.println("Audio를 켭니다."); } @Override public void turnOff() { System.out.println("Audio를 끕니다."); } @Override public void getVolume() { System.out.println(this.volume); } @Override public void setVolume(int volume) { if (volume > RemoteControl.MAX_VOLUME) { this.volume = RemoteControl.MAX_VOLUME; } else if (volume < RemoteControl.MIN_VOLUME) { this.volume = RemoteControl.MIN_VOLUME; } else { this.volume = volume; } System.out.println("현재 Audio volume: " + this.volume); } @Override public void setMute(boolean mute) { if(mute) { this.memoryVolume = this.volume; System.out.println("무음 처리합니다."); setVolume(MIN_VOLUME); }else { System.out.println("무음 해제합니다."); setVolume(this.memoryVolume); } } }

RemoteConExam.java

package ch08; public class RemoteConExam { public static void main(String[] args) { // 인터페이스 타입은 그 구현 클래스를 모두 담을 수 있음 // 그 타입에 명시된 메서드만 visible함. RemoteControl rc; // 인터페이스는 설계도의 개념이라 구현할 수 없다. // RemoteControl rc = new RemoteControl(); 같은 표현은 틀린 것. // rc라는 객체는 인터페이스에게 메소드를 호출하면 인터페이스가 알아서 리턴값을 맞게 돌려주는 것 rc = new Television(); rc.turnOn(); rc.setVolume(5); rc.turnOff(); rc.setMute(true); rc.setMute(false); System.out.println(""); rc= new Audio(); rc.turnOn(); rc.setVolume(11); rc.turnOff(); rc.setMute(true); rc.setMute(false); System.out.println(""); RemoteControl.chanegBattery(); } }
 

핵심 키워드

  • 인터페이스의 선언은 interface 키워드를 사용하며, 접근 제한자로는 default, public을 붙일 수 있다.
  • implements 키워드를 통해 해당 클래스가 인터페이스를 구현할 수 있다.
  • 인터페이스에 선언된 필드는 모두 public static final 특성을 가진다.
  • 인터페이스는 구현 클래스가 재정의해야 하는 public 추상 메소드를 멤버로 가질 수 있다.
    • 추상 메소드는 리턴 타입, 메소드명, 매개변수만 기술되고 {}를 붙이지 않는다.
  • 인터페이스는 완전한 실행 코드를 가진 디폴트 메소드를 가질 수 있다.
    • 선언 방법은 default 키워드를 앞에 붙이는 것이다.
  • 인터페이스는 정적 메소드도 선언이 가능하다. 정적 메소드는 구현 객체가 없어도 인터페이스 만으로 호출이 가능하다.
    • 선언 방법은 클래스 정적 메소드와 동일하다.
 

Service.java

package ch08; public interface Service { // 인터페이스-구현-인터페이스화 해야 사용할 수 있는 메서드. 반드시 구현 객체를 만들어야 한다. default void defaultMethod1() { System.out.println("defaultMethod1 종속 코드"); defaultCommon(); } default void defaultMethod2() { System.out.println("defaultMethod2 종속 코드"); defaultCommon(); } private void defaultCommon() { System.out.println("defaultMethod 종속 코드 A"); System.out.println("defaultMethod 종속 코드 B"); } static void staticMethod1() { System.out.println("staticMethod1 종속 코드"); staticCommon(); } static void staticMethod2() { System.out.println("staticMethod2 종속 코드"); staticCommon(); } static void staticCommon() { System.out.println("staticMethod 종속 코드 C"); System.out.println("staticMethod 종속 코드 D"); } }

ServiceImpl.java

package ch08; public class ServiceImpl implements Service{ }

ServiceExample.java

package ch08; public class ServiceExample { public static void main(String[] args) { Service service = new ServiceImpl(); service.defaultMethod1(); System.out.println(); service.defaultMethod2(); System.out.println(); Service.staticMethod1(); System.out.println(); Service.staticMethod2(); System.out.println(); } }
 

핵심 키워드

  • private 메소드는 디폴트 메소드 안에서만 호출이 가능하고, private 정적 메소드는 정적 메소드 안에서도 호출이 가능하다.
 

RemoteCon.java

package ch08; public interface RemoteCon { void turnOn(); void turnOff(); }

Searchable.java

package ch08; public interface Searchable { void search(String url); }

SmartTelevision.java

package ch08; public interface SmartTelevision extends RemoteCon, Searchable{ }

SmartTelevisionImpl.java

package ch08; public class SmartTelevisionImpl implements SmartTelevision { @Override public void turnOn() { System.out.println("TV를 켭니다."); } @Override public void turnOff() { System.out.println("TV를 끕니다."); } @Override public void search(String url) { System.out.println(url + "을 검색합니다."); } }

MultipleInterfaceImplExample.java

package ch08; public class MultipleInterfaceImplExample { public static void main(String[] args) { RemoteCon rc = new SmartTelevisionImpl(); rc.turnOn(); rc.turnOff(); Searchable searchable = new SmartTelevisionImpl(); searchable.search("https://www.youtube.com"); SmartTelevision st = new SmartTelevisionImpl(); st.turnOn(); st.turnOff(); st.search("https://www.youtube.com"); } }
 

핵심 키워드

  • 구현 객체는 여러 개의 인터페이스를 implements 할 수 있다. 구현 객체가 여러 인터페이스를 구현하고 있다면, 각각의 인터페이스를 통해 구현 객체를 사용할 수 있다.
  • 구현 객체가 어떤 인터페이스 변수에 대입되느냐에 따라 변수를 통해 호출할 수 있는 추상 메소드가 결정된다.
 

Vehicle.java

package ch08; public interface Vehicle { void run(); }

Bus.java

package ch08; public class Bus implements Vehicle{ @Override public void run() { System.out.println("버스가 달립니다."); } public void checkFare() { System.out.println("승차요금을 체크합니다."); } }

Taxi.java

package ch08; public class Taxi implements Vehicle{ @Override public void run() { System.out.println("택시가 달립니다."); } }

BusExam.java

package ch08; public class BusExam { public static void main(String[] args) { Vehicle vehicle = new Bus(); vehicle.run(); // vehicle.checkFare(); // non-visable 하기 떄문 System.out.println(); Bus bus = (Bus)vehicle; bus.run(); bus.checkFare(); System.out.println(); Vehicle taxi = new Taxi(); ride(taxi); ride(bus); } static void ride(Vehicle v) { v.run(); // v.checkFare(); // Bus에는 있지만 Vehicle 에는 없기 때문에 non-visible if(v instanceof Bus b) { // 따라서 instanceof 사용. b.checkFare(); } } }
 

핵심 키워드

  • 강제 타입 변환은 캐스팅 기호를 사용해서 인터페이스 타입을 구현 클래스 타입으로 변환시키는 것이다.
  • 구현 객체가 인터페이스 타입으로 자동 변환되면, 인터페이스에 선언된 메소드만 사용 가능하다.
    • 만약 자동 타입 변환 후에 non-visible해진 메소드를 사용하고 싶다면 캐스팅 기호를 사용해서 원래 타입으로 강제 타입 변환해야 한다.
 

InterfaceA.java

package ch08; // sealed를 인터페이스에 쓰면 구현을 막는게 아닌 상속을 막는 것 public sealed interface InterfaceA permits InterfaceB{ void methodA(); }

InterfaceB.java

package ch08; public non-sealed interface InterfaceB extends InterfaceA{ void methodB(); }

InterfaceC.java

package ch08; public interface InterfaceC extends InterfaceB{ void methodC(); }

ImplClass.java

package ch08; public class ImplClass implements InterfaceC{ @Override public void methodB() { System.out.println("methodB 실행"); } @Override public void methodA() { System.out.println("methodA 실행"); } @Override public void methodC() { System.out.println("methodC 실행"); } }

SealedExample.java

package ch08; public class SealedExample { public static void main(String[] args) { ImplClass impl = new ImplClass(); InterfaceA ia = impl; ia.methodA(); InterfaceB ib = impl; ib.methodA(); ib.methodB(); InterfaceC ic = impl; ic.methodA(); ic.methodB(); ic.methodC(); } }
 

핵심 키워드

  • 인터페이스도 다른 인터페이스를 상속할 수 있으며, 클래스와는 달리 다중 상속을 허용한다.
  • 부모 클래스가 인터페이스를 구현하고 있다면 자식 클래스도 인터페이스 타입으로 자동 타입 변환된다. 또한 자식 객체는 부모 객체로 자동 변환될 수 있다.
  • 인터페이스 타입을 구현 클래스 타입으로 변환할 때는 강제 타입 변환이 필요하다.
  • 자바 15부터는 무분별한 자식 인터페이스 생성을 방지하기 위해 sealed 인터페이스를 사용할 수 있다.
    • sealed 키워드를 사용하면 permits 키워드 위에 상속 가능한 자식 인터페이스를 지정해야 한다.
    • 자식 인터페이스는 non-sealed 키워드를 사용해서 선언하거나, 또는 sealed 키워드를 사용해서 또 다른 봉인 인터페이스로 선언해야 한다.
 

결론

해당 문제를 풀면서 자바에서 인터페이스가 가지는 역할과 그 기능을 익힐 수 있었다.
Share article

More articles

See more posts

👨🏻‍💻DriedPollack's Blog