인터페이스 : 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할을 하는 일종의 추상 클래스
어떤 객체가 특정 인터페이스를 사용한다면 그 객체는 반드시 인터페이스의 메소드들을 구현해야 한다.
다음은 어떤 동물원의 사육사가 하는 일이다.
난 동물원(zoo)의 사육사(zookeeper)이다.
육식동물(predator)이 들어오면 난 먹이를 던져준다(feed).
- 호랑이(tiger)가 오면 고기(meat)를 던져준다.
- 사자(lion)가 오면 생선(fish)를 던져준다.
package chapter08;
import java.util.ArrayList;
import java.util.List;
public class Sample {
public static void main(String[] args) {
Zookeeper zookeeper = new Zookeeper();
Lion lion = new Lion();
zookeeper.feed(lion);
Tiger tiger = new Tiger();
zookeeper.feed(tiger);
Crocodile crocodile = new Crocodile();
zookeeper.feed(crocodile);
// Predator[] predators = {lion, tiger, crocodile};
Predator predator = new Lion();
}
}
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal implements Predator {
@Override
public String getFood() {
return "meat";
}
}
class Lion extends Animal implements Predator {
@Override
public String getFood() {
return "fish";
}
}
class Crocodile extends Animal implements Predator {
@Override
public String getFood() {
return "strawberry";
}
}
class Zookeeper {
void feed(Predator predator) {
System.out.println("feed " + predator.getFood());
}
}
package chapter08;
public interface Predator { // 육식동물 인터페이스
String getFood();
}
추상클래스는 하나밖에 상속받지 못하지만 인터페이스는 다중 구현이 가능하다
추상클래스는 상속을 통해 기능을 확장해나가는 목적으로 자주 사용
하나의 상위 클래스로 묶는것이 가능한 경우, 상속을 한다.
완전 구현한 메소드와 바디부분이 없는 메소드 둘다 구현 가능
인터페이스는 기능 확장이라기보다는 뼈대를 클래스로 가져와서 살을 붙이는 느낌으로 사용한다.
클래스들이 가지는 공통된 특징을 정의해둔 것이라고 생각하면 편할 듯? (여기 해당되면 너도 우리 인터페이스야)
인터페이스에서도 필드는 선언이 가능하지만 static final인 상수로만 선언할 수 있다.
2. 인터페이스 구현과 사용
설명 보기
인터페이스의 메소드는 메소드의 이름과 입출력에대한 정의만 있고 내용이 없다
인터페이스 == implements한 클래스들이 강제적으로 구현해야하는 규칙이기 때문
interface 인터페이스명 {
타입 메소드명();
}
Predator tiger = new Tiger(); 이 가능한 이유?
Predator tiger = (Predator) new Tiger(); 과 동일
개발 코드에서 인터페이스는 클래스의 필드, 생성자 또는 메소드의 매개변수, 생성자 또는 메소드의 로컬변수로 선언될 수 있다 (타입처럼 사용이 가능하다)
3. 인터페이스 상속
설명 보기
public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2, ... {
...
}
다중 상속을 허용한다
상속받은 인터페이스를 implements 받으면, abc인터페이스의 메소드를 모두 구현해야한다.
4. 인터페이스의 다형성
설명 보기
다형성 : 하나의 타입에 대입되는 객체에 따라 실행결과가 다양한 형태로 나오는 성질
public interface ProfileRepository {
void save();
}
public class ProfileService {
ProfileRepository repository;
public void saveProfile() {
repository = new ProfileDBRepository(); // 이 부분만 바꿔 끼우면 됨
repository.save();
}
}
public class ProfileDBRepository implements ProfileRepository {
@Override
public void save() {
System.out.println("DB에 프로필 저장하는 기능");
}
}
public class ProfileMemoryRepository implements ProfileRepository {
@Override
public void save() {
System.out.println("메모리에 프로필 저장하는 기능");
}
}
자동타입변환
구현 객체가 인터페이스 타입으로 변환
장점 : 여러가지 구현 클래스들이 들어올 수 있다.
일반클래스 변수명 = new 일반클래스();
인터페이스명 변수명 = new 구현클래스;
//구현클래스가 인터페이스로 자동 타입변환이 일어난다.
//인터페이스명 타입으로 구현객체를 품을 수 있다.
public class Driver {
public void drive(Vehicle vehicle) { // 구현 객체 vehicle
vehicle.run(); // 구현 객체의 run() 메소드가 실행됨
}
}
public class DriverExample {
public static void main(String[] args) {
Driver driver = new Driver();
Vehicle taxi = new Taxi();
driver.drive(taxi); // 전달한 구현 객체로 자동 타입 변환 : Vehicle vehicle = taxi;
Vehicle bus = new Bus();
driver.drive(bus); // 전달한 구현 객체로 자동 타입 변환 : Vehicle vehicle = bus;
}
}