인터페이스는 사전적인 의미로 두 장치를 연결하는 접속기를 말합니다. 이러한 개념이 소프트웨어 개발에서 파생되어 객체지향 프로그래밍 언어에서 "인터페이스"는 클래스 간의 상호 작용을 정의하거나, 클래스와 클라이언트 간의 계약을 명시하는 역할을 합니다.
주요 특징:
1. 추상 메소드의 집합: 인터페이스는 일반적으로 추상 메소드들의 집합을 정의하며, 구현을 갖지 않습니다.
2. 상수 (static final 필드): 상수 필드를 가질 수 있으며, 이는 인터페이스에서 정의된 값이 변경되지 않도록 합니다.
3. 다중 상속: 클래스는 다중 상속을 허용하지 않지만, 인터페이스는 다중 상속을 지원합니다.
예시:
// 인터페이스 선언
interface Connectable {
void connect();
}
// 인터페이스를 구현하는 클래스
class Device implements Connectable {
@Override
public void connect() {
System.out.println("Device connected");
}
}
// 또 다른 인터페이스 구현
class Network implements Connectable {
@Override
public void connect() {
System.out.println("Network connected");
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
Connectable device = new Device();
device.connect(); // Device connected
Connectable network = new Network();
network.connect(); // Network connected
}
}
인터페이스의 활용:
인터페이스는 객체지향 프로그래밍에서 다형성(Polymorphism)을 구현하는 주요 기술 중 하나입니다. 다형성은 코드의 유연성과 재사용성을 높이는데 기여하며, 인터페이스는 이러한 다형성을 가능케 하는 핵심 도구로 활용됩니다.
1. 다형성의 핵심 개념:
2. 인터페이스를 통한 다형성:
3. 예시:
// 다형성을 위한 인터페이스 선언
interface Shape {
void draw();
}
// 인터페이스를 구현하는 다양한 도형 클래스
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Circle");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Rectangle");
}
}
class Triangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Triangle");
}
}
// 클라이언트 코드에서 다형성 활용
public class Main {
public static void main(String[] args) {
// 다양한 도형을 하나의 인터페이스로 다룰 수 있음
Shape circle = new Circle();
Shape rectangle = new Rectangle();
Shape triangle = new Triangle();
// 인터페이스의 메소드를 통해 각 도형의 draw() 메소드 호출
circle.draw(); // Drawing Circle
rectangle.draw(); // Drawing Rectangle
triangle.draw(); // Drawing Triangle
}
}
4. 다형성의 장점:
1. 인터페이스 선언:
인터페이스는 클래스들이 구현해야 하는 메소드의 명세를 정의하는데 사용되며, 이를 선언할 때는 class
키워드 대신 interface
키워드를 사용합니다.
예시:
// 인터페이스 선언
public interface MyInterface {
// 추상 메소드
void abstractMethod();
// 디폴트 메소드 (Java 8 이후에서 사용 가능)
default void defaultMethod() {
System.out.println("Default Method");
}
}
2. 접근 제한자:
인터페이스 내부의 멤버들에는 기본적으로 public
접근 제한자가 적용됩니다. 또한, Java 9부터는 디폴트 메소드와 정적 메소드에 대해 private
, private static
, private default
와 같은 제한자를 사용하여 접근 범위를 조절할 수 있습니다.
예시:
public interface MyInterface {
// public 접근 제한자가 기본
void abstractMethod();
// 디폴트 메소드 (public 접근 제한자가 기본)
default void defaultMethod() {
System.out.println("Default Method");
}
// 정적 메소드 (public 접근 제한자가 기본)
static void staticMethod() {
System.out.println("Static Method");
}
// Java 9 이후에서 사용 가능한 private 메소드
// (내부에서만 사용 가능)
private void privateMethod() {
System.out.println("Private Method");
}
}
3. 정리:
인터페이스 선언: interface
키워드를 사용하여 추상 메소드의 집합을 정의하고, 기본적으로 public
접근 제한자가 적용됩니다.
디폴트 메소드: Java 8 이후에서 사용 가능하며, 기존의 인터페이스에 새로운 기능을 추가할 때 유용하게 활용됩니다.
정적 메소드: Java 8 이후에서 사용 가능하며, 특정 클래스에 종속되지 않는 기능을 제공할 때 사용됩니다.
Java 9 이후의 private 메소드: 인터페이스 내에서만 사용되는 메소드로, 구현 세부 사항을 숨기고 내부 구현을 단순화합니다.
1. 개념:
{}
) 내용이 없는 메소드를 말합니다.2. 선언 방법:
abstract
키워드를 사용하여 선언됩니다.3. 역할:
4. 예시:
// 추상 클래스 선언
abstract class Shape {
// 추상 메소드 선언 (구현부 없음)
abstract void draw();
}
// 추상 메소드를 구현한 구체적인 클래스
class Circle extends Shape {
// 추상 메소드 구현
@Override
void draw() {
System.out.println("Drawing Circle");
}
}
5. 장점:
1. 클래스 B의 역할:
2. 인터페이스 구현:
public class B implements 인터페이스명
의 형태로 클래스 B가 특정 인터페이스를 구현함을 선언합니다.3. 인터페이스 구현의 의미:
4. 예시 코드:
// 인터페이스 선언
interface MyInterface {
void myMethod();
}
// 인터페이스를 구현하는 클래스 B
public class B implements MyInterface {
// 인터페이스의 추상 메소드를 구현
@Override
public void myMethod() {
System.out.println("Implementation of myMethod in class B");
}
// 클래스 B의 다른 메소드들
public void anotherMethod() {
System.out.println("Another method in class B");
}
}
5. 클래스 B의 활용:
myMethod
를 반드시 구현하고, 나머지 클래스의 메소드는 추가적으로 정의할 수 있습니다.6. 장점:
implements
키워드의 역할 및 의미1. 역할:
implements
키워드는 클래스가 특정 인터페이스를 구현한다는 것을 나타내는 역할을 합니다.2. 사용 목적:
implements
키워드를 사용합니다.3. 표시의미:
implements
키워드는 해당 클래스가 특정 인터페이스의 규약을 따르며, 해당 인터페이스에 정의된 추상 메소드를 구현하겠다는 의미를 갖습니다.4. 추상 메소드의 재정의:
5. 예시 코드:
// 인터페이스 선언
interface MyInterface {
void myMethod();
}
// 클래스가 인터페이스를 구현
public class MyClass implements MyInterface {
// 인터페이스의 추상 메소드를 재정의
@Override
public void myMethod() {
System.out.println("Implementation of myMethod in MyClass");
}
// MyClass의 다른 메소드들
public void anotherMethod() {
System.out.println("Another method in MyClass");
}
}
6. 재정의와 다형성:
implements
키워드를 사용하여 인터페이스를 구현하면, 해당 클래스는 인터페이스의 메소드를 재정의함으로써 다형성을 구현할 수 있습니다.7. 정리:
implements
키워드를 통해 클래스는 특정 인터페이스를 구현하고, 해당 인터페이스의 규약을 준수하는 메소드들을 제공함으로써 다형성과 유연성을 제공합니다.1. 인터페이스의 타입:
2. 변수의 타입으로 활용:
3. 다형성의 구현:
4. 예시 코드:
// 인터페이스 선언
interface MyInterface {
void myMethod();
}
// 인터페이스를 구현하는 클래스
class MyClass implements MyInterface {
@Override
public void myMethod() {
System.out.println("Implementation of myMethod in MyClass");
}
// MyClass의 다른 메소드들
public void anotherMethod() {
System.out.println("Another method in MyClass");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스를 타입으로 사용하는 변수 선언
MyInterface myObject = new MyClass();
// 인터페이스의 메소드 호출
myObject.myMethod(); // 출력: Implementation of myMethod in MyClass
// myObject는 MyInterface 타입이지만, MyClass의 다른 메소드는 호출할 수 없음
// myObject.anotherMethod(); // 에러: cannot find symbol
}
}
5. 장점:
1. 다형성을 통한 유연한 객체 대입:
2. 예시 코드:
// 인터페이스 선언
interface MyInterface {
void myMethod();
}
// 인터페이스를 구현하는 클래스 A
class ClassA implements MyInterface {
@Override
public void myMethod() {
System.out.println("Implementation of myMethod in ClassA");
}
}
// 인터페이스를 구현하는 클래스 B
class ClassB implements MyInterface {
@Override
public void myMethod() {
System.out.println("Implementation of myMethod in ClassB");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스 변수에 구현 객체 대입
MyInterface objectA = new ClassA();
MyInterface objectB = new ClassB();
// 다형성을 활용한 메소드 호출
objectA.myMethod(); // 출력: Implementation of myMethod in ClassA
objectB.myMethod(); // 출력: Implementation of myMethod in ClassB
}
}
3. 장점:
1. 상수 필드 선언:
public static final
특성을 갖는 불변의 상수 필드를 선언할 수 있습니다.2. 상수 필드의 특성:
public static final
로 선언된 상수 필드는 모든 구현 클래스에서 동일한 값을 가지며, 변경될 수 없습니다.3. 예시 코드:
// 인터페이스 선언 (상수 필드를 갖는)
interface MyInterface {
// 불변의 상수 필드 선언
public static final int MAX_VALUE = 100;
public static final String DEFAULT_NAME = "Default";
}
// 인터페이스를 구현하는 클래스
class MyClass implements MyInterface {
// MyClass에서는 MyInterface의 상수 필드를 참조할 수 있음
public void printConstants() {
System.out.println("Max Value: " + MAX_VALUE);
System.out.println("Default Name: " + DEFAULT_NAME);
}
}
public class Main {
public static void main(String[] args) {
// MyClass의 객체 생성
MyClass myObject = new MyClass();
// 상수 필드 출력
myObject.printConstants();
}
}
4. 장점 및 활용:
1. 구현 객체와 무관한 상수:
2. 직접 접근의 특성:
3. 예시 코드:
// 인터페이스 선언 (상수 필드를 갖는)
interface MyInterface {
// 불변의 상수 필드 선언
public static final int MAX_VALUE = 100;
public static final String DEFAULT_NAME = "Default";
}
public class Main {
public static void main(String[] args) {
// 인터페이스 상수 직접 접근
System.out.println("Max Value: " + MyInterface.MAX_VALUE);
System.out.println("Default Name: " + MyInterface.DEFAULT_NAME);
}
}
4. 장점 및 활용:
1. 추상 메소드의 선언:
2. 구현 클래스의 의무:
3. 예시 코드:
// 인터페이스 선언 (추상 메소드를 갖는)
interface MyInterface {
// 추상 메소드 선언
void myAbstractMethod();
}
// 인터페이스를 구현하는 클래스
class MyClass implements MyInterface {
// 인터페이스의 추상 메소드를 구현
@Override
public void myAbstractMethod() {
System.out.println("Implementation of myAbstractMethod in MyClass");
}
// MyClass의 다른 메소드들
public void anotherMethod() {
System.out.println("Another method in MyClass");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스를 구현한 객체 생성
MyClass myObject = new MyClass();
// 추상 메소드 호출
myObject.myAbstractMethod(); // 출력: Implementation of myAbstractMethod in MyClass
// MyClass의 다른 메소드 호출
myObject.anotherMethod(); // 출력: Another method in MyClass
}
}
4. 장점 및 활용:
1. 기본적인 public 접근 제한:
public
접근 제한을 갖습니다.2. 재정의 메소드에 public 추가:
public
접근 제한자를 명시해야 합니다.3. 예시 코드:
// 인터페이스 선언 (추상 메소드를 갖는)
interface MyInterface {
// 추상 메소드 선언 (기본적으로 public)
void myAbstractMethod();
}
// 인터페이스를 구현하는 클래스
class MyClass implements MyInterface {
// 인터페이스의 추상 메소드를 구현 (public 추가)
@Override
public void myAbstractMethod() {
System.out.println("Implementation of myAbstractMethod in MyClass");
}
// MyClass의 다른 메소드들
public void anotherMethod() {
System.out.println("Another method in MyClass");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스를 구현한 객체 생성
MyClass myObject = new MyClass();
// 추상 메소드 호출
myObject.myAbstractMethod(); // 출력: Implementation of myAbstractMethod in MyClass
}
}
4. 재정의의 명시성과 일관성:
@Override
어노테이션을 사용하여 메소드의 명시성을 강조하면서, 일관된 코드 스타일을 유지할 수 있습니다.1. 인터페이스 변수의 다형성:
2. 다양한 실행 내용:
3. 예시 코드:
// 인터페이스 선언 (추상 메소드를 갖는)
interface MyInterface {
// 추상 메소드 선언
void myAbstractMethod();
}
// 구현 클래스 A
class ClassA implements MyInterface {
@Override
public void myAbstractMethod() {
System.out.println("Implementation in ClassA");
}
}
// 구현 클래스 B
class ClassB implements MyInterface {
@Override
public void myAbstractMethod() {
System.out.println("Implementation in ClassB");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스 변수에 구현 객체 대입
MyInterface objA = new ClassA();
MyInterface objB = new ClassB();
// 다형성을 통한 메소드 호출
objA.myAbstractMethod(); // 출력: Implementation in ClassA
objB.myAbstractMethod(); // 출력: Implementation in ClassB
}
}
4. 다형성의 장점:
1. 디폴트 메소드의 선언:
default
키워드를 사용하여 선언됩니다.2. 실행 코드 포함:
3. 예시 코드:
// 인터페이스 선언 (디폴트 메소드를 갖는)
interface MyInterface {
// 추상 메소드 선언
void myAbstractMethod();
// 디폴트 메소드 선언
default void myDefaultMethod() {
System.out.println("Default implementation in MyInterface");
}
}
// 인터페이스를 구현하는 클래스
class MyClass implements MyInterface {
// 추상 메소드의 구현
@Override
public void myAbstractMethod() {
System.out.println("Implementation of myAbstractMethod in MyClass");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스를 구현한 객체 생성
MyClass myObject = new MyClass();
// 추상 메소드 호출
myObject.myAbstractMethod(); // 출력: Implementation of myAbstractMethod in MyClass
// 디폴트 메소드 호출
myObject.myDefaultMethod(); // 출력: Default implementation in MyInterface
}
}
4. 장점 및 활용:
1. 구현 클래스에서 디폴트 메소드 재정의:
2. 메소드 재정의의 명시성:
@Override
어노테이션을 사용하여 명시성을 강조합니다.3. 예시 코드:
// 인터페이스 선언 (디폴트 메소드를 갖는)
interface MyInterface {
// 디폴트 메소드 선언
default void myDefaultMethod() {
System.out.println("Default implementation in MyInterface");
}
}
// 인터페이스를 구현하는 클래스
class MyClass implements MyInterface {
// 디폴트 메소드의 재정의
@Override
public void myDefaultMethod() {
System.out.println("Custom implementation in MyClass");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스를 구현한 객체 생성
MyClass myObject = new MyClass();
// 디폴트 메소드 호출 (구현 클래스에서 재정의된 메소드 실행)
myObject.myDefaultMethod(); // 출력: Custom implementation in MyClass
}
}
4. 재정의의 활용:
1. 정적 메소드의 선언:
static
키워드를 사용하여 선언되며, 구현 객체 없이도 인터페이스를 통해 직접 호출할 수 있습니다.2. 구현 객체의 필요 없음:
3. 예시 코드:
// 인터페이스 선언 (정적 메소드를 갖는)
interface MyInterface {
// 정적 메소드 선언
static void myStaticMethod() {
System.out.println("Static method in MyInterface");
}
}
public class Main {
public static void main(String[] args) {
// 정적 메소드 호출 (구현 객체 없이 인터페이스를 통해 직접 호출)
MyInterface.myStaticMethod(); // 출력: Static method in MyInterface
}
}
4. 정적 메소드의 활용:
1. private 메소드의 선언:
2. private 정적 메소드의 선언:
3. private 메소드의 활용:
4. 예시 코드:
// 인터페이스 선언 (private 메소드를 갖는)
interface MyInterface {
// 추상 메소드
void myAbstractMethod();
// default 메소드
default void myDefaultMethod() {
// private 메소드 호출 (구현 객체가 필요한 메소드)
myPrivateMethod();
System.out.println("Default implementation in MyInterface");
}
// private 메소드 (구현 객체가 필요한)
private void myPrivateMethod() {
System.out.println("Private method in MyInterface");
}
// private 정적 메소드 (구현 객체가 필요하지 않는)
private static void myStaticPrivateMethod() {
System.out.println("Static private method in MyInterface");
}
}
public class Main {
public static void main(String[] args) {
// 인터페이스를 구현한 객체 생성
MyInterface myObject = new MyInterface() {
// 추상 메소드의 구현
@Override
public void myAbstractMethod() {
System.out.println("Implementation of myAbstractMethod");
}
};
// default 메소드 호출
myObject.myDefaultMethod(); // 출력: Private method in MyInterface, Default implementation in MyInterface
// private 정적 메소드 호출 (인터페이스명을 통해 호출)
MyInterface.myStaticPrivateMethod(); // 출력: Static private method in MyInterface
}
}
5. private 메소드의 장점:
1. 다중 인터페이스 구현:
implements
키워드를 사용하여 여러 인터페이스를 쉼표로 구분하여 나열합니다.2. 구현 객체의 특성 활용:
3. 예시 코드:
// 첫 번째 인터페이스 선언
interface InterfaceA {
void methodA();
}
// 두 번째 인터페이스 선언
interface InterfaceB {
void methodB();
}
// 다중 인터페이스를 구현하는 클래스
class MultiInterfaceClass implements InterfaceA, InterfaceB {
// 첫 번째 인터페이스의 메소드 구현
@Override
public void methodA() {
System.out.println("Implementation of methodA");
}
// 두 번째 인터페이스의 메소드 구현
@Override
public void methodB() {
System.out.println("Implementation of methodB");
}
}
public class Main {
public static void main(String[] args) {
// 다중 인터페이스를 구현한 객체 생성
MultiInterfaceClass multiObject = new MultiInterfaceClass();
// 각 인터페이스의 메소드 호출
multiObject.methodA(); // 출력: Implementation of methodA
multiObject.methodB(); // 출력: Implementation of methodB
}
}
4. 장점 및 활용:
1. 인터페이스 간의 상속:
2. 구현 클래스의 의무:
3. 예시 코드:
// 부모 인터페이스 선언
interface ParentInterface {
void parentMethod();
}
// 자식 인터페이스 선언 (부모 인터페이스를 상속)
interface ChildInterface extends ParentInterface {
void childMethod();
}
// 구현 클래스 (자식 인터페이스 구현)
class ImplementingClass implements ChildInterface {
// 자식 인터페이스의 메소드 구현
@Override
public void childMethod() {
System.out.println("Implementation of childMethod");
}
// 부모 인터페이스의 메소드 구현
@Override
public void parentMethod() {
System.out.println("Implementation of parentMethod");
}
}
public class Main {
public static void main(String[] args) {
// 구현 클래스 생성
ImplementingClass obj = new ImplementingClass();
// 자식 인터페이스의 메소드 호출
obj.childMethod(); // 출력: Implementation of childMethod
// 부모 인터페이스의 메소드 호출
obj.parentMethod(); // 출력: Implementation of parentMethod
}
}
4. 다중 상속의 활용:
1. 자식 인터페이스 변수에 대입:
2. 부모 인터페이스 변수에 대입:
3. 예시 코드:
// 부모 인터페이스 선언
interface ParentInterface {
void parentMethod();
}
// 자식 인터페이스 선언 (부모 인터페이스를 상속)
interface ChildInterface extends ParentInterface {
void childMethod();
}
// 구현 클래스 (자식 인터페이스 구현)
class ImplementingClass implements ChildInterface {
// 자식 인터페이스의 메소드 구현
@Override
public void childMethod() {
System.out.println("Implementation of childMethod");
}
// 부모 인터페이스의 메소드 구현
@Override
public void parentMethod() {
System.out.println("Implementation of parentMethod");
}
}
public class Main {
public static void main(String[] args) {
// 구현 객체를 자식 인터페이스 변수에 대입
ChildInterface childVar = new ImplementingClass();
// 자식 인터페이스의 메소드 호출
childVar.childMethod(); // 출력: Implementation of childMethod
// 부모 인터페이스의 메소드 호출 (다형성)
childVar.parentMethod(); // 출력: Implementation of parentMethod
// 구현 객체를 부모 인터페이스 변수에 대입
ParentInterface parentVar = new ImplementingClass();
// 자식 인터페이스의 메소드는 호출할 수 없음
// parentVar.childMethod(); // 에러 발생
// 부모 인터페이스의 메소드 호출
parentVar.parentMethod(); // 출력: Implementation of parentMethod
}
}
4. 다형성의 활용:
1. 자동 타입 변환:
2. 강제 타입 변환:
3. 예시 코드:
// 부모 인터페이스 선언
interface ParentInterface {
void parentMethod();
}
// 구현 클래스 (인터페이스 구현)
class ImplementingClass implements ParentInterface {
// 부모 인터페이스의 메소드 구현
@Override
public void parentMethod() {
System.out.println("Implementation of parentMethod");
}
// 구현 클래스 자체의 메소드
void additionalMethod() {
System.out.println("Additional method in ImplementingClass");
}
}
public class Main {
public static void main(String[] args) {
// 구현 객체 생성
ImplementingClass obj = new ImplementingClass();
// 자동 타입 변환 (부모 인터페이스로)
ParentInterface parentVar = obj;
// 부모 인터페이스의 메소드 호출 (자동 타입 변환)
parentVar.parentMethod(); // 출력: Implementation of parentMethod
// 추가 메소드는 호출할 수 없음 (부모 인터페이스에 없는 메소드)
// parentVar.additionalMethod(); // 에러 발생
// 강제 타입 변환 (다시 구현 클래스로)
ImplementingClass backToClass = (ImplementingClass) parentVar;
// 구현 클래스의 메소드 호출 (강제 타입 변환 후)
backToClass.additionalMethod(); // 출력: Additional method in ImplementingClass
}
}
4. 다형성과 유연성 활용:
1. 매개변수의 다형성:
2. 예시 코드:
// 인터페이스 선언
interface MyInterface {
void interfaceMethod();
}
// 구현 클래스1 (인터페이스 구현)
class Implementation1 implements MyInterface {
@Override
public void interfaceMethod() {
System.out.println("Implementation1 of interfaceMethod");
}
}
// 구현 클래스2 (인터페이스 구현)
class Implementation2 implements MyInterface {
@Override
public void interfaceMethod() {
System.out.println("Implementation2 of interfaceMethod");
}
}
// 메소드의 매개변수로 인터페이스 타입 지정
void myMethod(MyInterface param) {
// 인터페이스의 메소드 호출
param.interfaceMethod();
}
public class Main {
public static void main(String[] args) {
// 구현 객체1을 매개변수로 전달
MyInterface obj1 = new Implementation1();
myMethod(obj1); // 출력: Implementation1 of interfaceMethod
// 구현 객체2를 매개변수로 전달
MyInterface obj2 = new Implementation2();
myMethod(obj2); // 출력: Implementation2 of interfaceMethod
}
}
3. 다형성을 활용한 장점:
1. instanceof 연산자:
2. 예시 코드:
// 인터페이스 선언
interface MyInterface {
void interfaceMethod();
}
// 구현 클래스 (인터페이스 구현)
class ImplementationClass implements MyInterface {
@Override
public void interfaceMethod() {
System.out.println("ImplementationClass of interfaceMethod");
}
// 클래스 자체의 메소드
void additionalMethod() {
System.out.println("Additional method in ImplementationClass");
}
}
public class Main {
public static void main(String[] args) {
// 구현 객체 생성
MyInterface obj = new ImplementationClass();
// instanceof를 통한 타입 확인
if (obj instanceof MyInterface) {
System.out.println("obj is an instance of MyInterface");
}
// 추가 메소드를 호출하기 위해 타입 변환
if (obj instanceof ImplementationClass) {
ImplementationClass implObj = (ImplementationClass) obj;
implObj.additionalMethod(); // 출력: Additional method in ImplementationClass
}
}
}
3. 다형성과 instanceof 활용:
1. 봉인된 인터페이스:
2. non-sealed 키워드:
non-sealed
키워드를 사용합니다.3. 예시 코드:
// 봉인된 인터페이스 선언
public sealed interface SealedInterface permits ChildInterface1, ChildInterface2 {
void commonMethod();
}
// 봉인된 인터페이스의 봉인 해제 (non-sealed)
public non-sealed interface ChildInterface1 extends SealedInterface {
void specificMethod1();
}
// 봉인된 인터페이스의 봉인 해제 (non-sealed)
public non-sealed interface ChildInterface2 extends SealedInterface {
void specificMethod2();
}
// 봉인된 인터페이스의 자식 인터페이스 (non-sealed)
public non-sealed interface ChildInterface3 extends SealedInterface {
void specificMethod3();
}
// 구현 클래스 (봉인된 인터페이스의 자식 인터페이스 구현)
class ImplementationClass1 implements ChildInterface1 {
@Override
public void commonMethod() {
System.out.println("ImplementationClass1 of commonMethod");
}
@Override
public void specificMethod1() {
System.out.println("ImplementationClass1 of specificMethod1");
}
}
public class Main {
public static void main(String[] args) {
// 구현 객체 생성
ChildInterface1 obj1 = new ImplementationClass1();
// 봉인된 인터페이스의 메소드 호출
obj1.commonMethod(); // 출력: ImplementationClass1 of commonMethod
obj1.specificMethod1(); // 출력: ImplementationClass1 of specificMethod1
}
}
4. 봉인된 인터페이스와 non-sealed의 활용: