1. 하나의 인터페이스 구현 선언
public interface Car {
void run();
void stop();
}
public class Taxi implements Car {
@Override
public void run() {
System.out.println("택시가 달립니다.");
}
@Override
public void stop() {
System.out.println("택시가 멈춥니다.");
}
}
2. 여러 개의 인터페이스 구현 선언
public interface Car {
void run();
}
public interface Sound {
void beep();
}
public class Bus implements Car, Sound {
public void run() {
System.out.println("버스가 달립니다.");
}
public void beep() {
System.out.println("버스가 빵빵 경적을 울립니다.");
}
}
1. Car.java
public class Car {
class Tire {}
static class Engine {}
}
2. NestedClassExample.java
public class NestedClassExample {
public static void main (String[] args) {
Car myCar = new Car();
Car.Tire tire = myCar.new Tire(); //인스턴스 맴버 클래스 객체 생성
Car.Engine engine = new Car.Engine(); //정적 멤버 클래스 객체 생성
- 인스턴스 멤버 클래스는 외부 클래스(Car)의 객체가 먼저 있어야 생성 가능
- 정적 클래스는 외부 클래스 객체 없이도 생성 가능
인터페이스
1. 인터페이스(interface) 선언
public interface Car {
//상수
public static final String name = "자동차" //타입 상수 이름 = 값;
//추상 메소드
public abstract void stop();
public abstract void run(); // 타입 메소드이름(매개변수, );
}
인터페이스는 상수 필드와 추상 메소드만 가질 수 있음
인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없음
2. 인터페이스 구현 및 사용
public class Taxi implements Car{
@Override
//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
public void stop() {
System.out.println("택시가 멈춥니다");
}
@Override
public void run() {
System.out.println("택시가 달립니다");
}
}
public class Bicycle implements Car{
@Override
//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
public void stop() {
System.out.println("자전거가 멈춥니다");
}
@Override
public void run() {
System.out.println("자전거가 달립니다");
}
}
public class Main {
public static void main(String[] args) {
Car taxi = new Taxi();
Car bicycle = new Bicycle();
taxi.run();
taxi.stop();
bicycle.run();
bicycle.stop();
}
}
Car 인터페이스를 implements 키워드로 구현하고 인터페이스 추상 메서드들을 재정의!
3. 타입 변환과 다형성
위 코드를 보자
Car taxi = new Taxi();
Car bicycle = new Bicycle();
자식 → 부모로의 업캐스팅(자동) / 따라서 Car 인터페이스에 정의된 메서드만 호출 가능
1. Car. java (인터페이스)
public interface Car {
void run();
void stop();
}
2. Taxi.java (Car 구현 + 추가 기능)
public class Taxi implements Car {
@Override
public void run() {
System.out.println("택시가 달립니다.");
}
@Override
public void stop() {
System.out.println("택시가 멈춥니다.");
}
// Taxi에만 있는 고유 메서드
public void pickUpPassenger() {
System.out.println("승객을 태웁니다.");
}
}
3. Bicycle.java (Car 구현)
public class Bicycle implements Car{
@Override
public void stop() {
System.out.println("자전거가 멈춥니다");
}
@Override
public void run() {
System.out.println("자전거가 달립니다");
}
}
4. Main.java
public class Main {
public static void main(String[] args) {
Car car = new Taxi();
car.run(); // 택시가 달립니다.
car.stop(); // 택시가 멈춥니다.
// car.pickUpPassenger(); //오류 발생 Car 타입에는 없음
// 강제 타입 변환 - 다시 Taxi 타입으로 변환해야 가능
if (car instanceof Taxi) {
Taxi taxi = (Taxi) car; // 강제 타입 변환
taxi.pickUpPassenger();
}
// Bicycle은 pickUpPassenger 메서드 없음 → 다운캐스팅 불가
Car bicycle = new Bicycle();
if (bicycle instanceof Taxi) {
Taxi wrongTaxi = (Taxi) bicycle; // 실행 시 ClassCastException 오류 발생
wrongTaxi.pickUpPassenger();
} else {
System.out.println("이 객체는 Taxi가 아닙니다.");
}
}
}
강제 타입 변환을 하기 전에
instanceof
키워드를 사용해서 변환이 가능한 지 조사를 해야함
신경 안쓰고 그냥 했다간ClassCastException
오류 발생
4. 인터페이스의 상속
1. 인스턴스 멤버 클래스
class A {
class B{}
}
- A 객체를 생성해야만 사용 할 수 있는 B 클래스
- static 키워드 없이 중첩 선언된 클래스 → 인스턴스 필드와 메소드만 선언 가능 / 정적 필드와 메소드는 선언 불가 (static 붙은 건 사용 불가)
2. 정적 멤버 클래스
class A {
static class B{}
}
- A 클래스로 바로 접급할 수 있는 B 클래스
- static 키워드로 선언된 클래스 → 모든 종류의 필드와 메소드를 선언 가능
3. 로컬 클래스 → 생성자 또는 메소드 내부에서 선언되는 중첩 클래스
class A {
void method () {
class B {}
}
}
- method()가 실행할 때만 사용할 수 있는 B 클래스
- 매소드 내부에서만 사용하니까 → 접근제한자(public, private) 및 static 붙일 수 없음
1. 버튼 클릭 리스너
public class Button {
// 중첩 인터페이스
public interface OnClickListener {
void onClick(); // 추상 메서드
}
private OnClickListener listener;
// 외부에서 인터페이스 구현체를 전달 받는 메서드
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public void click() {
if (listener != null) {
listener.onClick();
}
}
}
2. Main 클래스
public class Main {
public static void main(String[] args) {
Button button = new Button();
// 중첩 인터페이스 구현
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick() {
System.out.println("버튼이 클릭되었습니다!");
}
});
button.click();
}
}