+) 인터페이스 안의 상수는 이미 상수이기때문에 static final 붙이지 않음. 또한 private도 사용하지 않는다. (아무것도 안쓴상태 = public)
+) 인터페이스엔 실제 body가 없고 이런 동작들을 할거다~ 선언만 하므로 추상메소드임.
[public] interface 인터페이스이름 {...}
[public static final] 타입 상수이름 = 값;
// 선언과 동시에 초기값 지정, 괄호는 디폴트라 생략가능
public interface RemoteControl {
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
}
[public abstract] 리턴타입 메소드이름(매개변수, ...);
//괄호는 디폴트
public interface RemoteControl {
public int MAX_VOLUME = 10;
public int MIN_VOLUME = 0;
//추상메소드
public void turnOn();
public void turnOff();
public void setVolume(int volume);
}
public class 구현클래스이름 implements 인터페이스이름{
// 인터페이스에 선언된 추상메소드의 실체메소드 선언
}
public class Television implements RemoteControl {
private int volume;
@Override
public void turnOn() {
System.out.println("티비를 켭니다");
}
@Override
public void turnOff() {
System.out.println("티비를 끕니다");
}
@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("현재 티비 볼륨: "+volume);
}
}
💡 구현클래스에서 인터페이스의 추상메소드의 실체메소드를 입력시, 인터페이스의 모든 메소드는 기본으로 public이기 때문에 그보다 더 낮은 접근제한자를 사용 할 수 없다.
public class RemoteControlExample{
public static void main(String[] args){
RemoteControl rc;
rc = new Television();
rc = new Audio();
// 인터페이스 변수 rc에 구현객체를 대입해서 사용
}
}
public class 구현클래스이름 implements 인터페이스A, 인터페이스B{
// 인터페이스A에 선언된 추상메소드의 실체메소드 선언
// 인터페이스B에 선언된 추상메소드의 실체메소드 선언
}
public interface Searchable {
void search(String url);
}
public class SmartTelevision implements RemoteControl, Searchable {
private int volume;
@Override
public void search(String url) {
System.out.println(url+"을 검색합니다");
}
@Override
public void turnOn() {
System.out.println("티비를 켭니다");
}
@Override
public void turnOff() {
System.out.println("티비를 끕니다");
}
@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("현재 티비 볼륨: "+this.volume);
}
}
public class SmartTelevisionExample {
public static void main(String[] args) {
SmartTelevision tv = new SmartTelevision();
RemoteControl rc = tv;
Searchable searchable = tv;
// 인터페이스 변수에 구현객체 대입
}
}
구현객체를 변수에 대입 한 이후엔 어떻게 해야할까?
public class MyClass {
//필드
RemoteControl rc = new Television();
//생성자
MyClass(RemoteControl rc){
//생성자의 매개값으로 구현객체 대입
this.rc = rc;
}
//메소드
void methodA() {
RemoteControl rc = new Audio();
//로컬변수
}
void methodB(RemoteControl rc) {
//메소드의 매개값으로 구현객체 대입
}
}
이렇게 구현객체가 인터페이스 타입에 대입되면 인터페이스에 선언된 추상메소드를 개발코드에서 사용할 수 있게 된다. RemoteControl의 변수 rc를 이용해 turnOn(), turnOff()메소드를 호출하면 구현객체의 turnOn()과 turnOff() 메소드가 실행된다.
(1) 필드로 선언된 rc
MyClass myClass = new MyClass();
myClass.rc.turnOn(); // Television의 turnOn() 실행
myClass.rc.setVolume(5); // Television의 setVolume(5) 실행
(2) 생성자의 매개변수타입으로 선언된 rc
MyClass( RemoteControl rc ) {
this.rc = rc;
rc.turnOn();
rc.setVolume(5);
}
오디오의 메소드를 실행하고 싶을 경우 아래처럼 하면 된다
MyClass myClass = new MyClass(new Audio));
(3) 로컬변수로 선언된 rc
void methodA(){
RemoteControl rc = new Audio();
rc.turnOn();
rc.setVolume(5);
}
(4) 메소드의 매개변수타입으로 선언된 rc
void methodB(RemoteControl rc){
rc.turnOn();
rc.setVolume(5);
}
다음과 같이 메소드가 호출되었을경우 Television의 메소드가 실행
MyClass myClass = new MyClass();
myClass.methodB(new Television());
public class MyClass {
//필드
RemoteControl rc = new Television();
//생성자
MyClass(){}
MyClass(RemoteControl rc){
//생성자의 매개값으로 구현객체 대입
this.rc = rc;
rc.turnOn();
rc.setVolume(5);
}
//메소드
void methodA() {
RemoteControl rc = new Audio();
rc.turnOn();
rc.setVolume(5);
}
void methodB(RemoteControl rc) {
rc.turnOn();
rc.setVolume(5);
}
}
public class MyClassExample {
public static void main(String[] args) {
System.out.println("1)----------------");
MyClass myClass1 = new MyClass();
myClass1.rc.turnOn();
myClass1.rc.setVolume(5);
// 실행결과 : 티비를켭니다 / 현재 티비볼륨:5
System.out.println("2)----------------");
MyClass myClass2 = new MyClass(new Audio());
// 실행결과 : 오디오를켭니다 / 현재 오디오볼륨:5
System.out.println("3)----------------");
MyClass myClass3 = new MyClass();
myClass3.methodA();
// 실행결과 : 오디오를켭니다 / 현재 오디오볼륨:5
System.out.println("4)----------------");
MyClass myClass4 = new MyClass();
myClass4.methodB(new Television());
// 실행결과 : 티비를켭니다 / 현재 티비볼륨:5
}
}
// 인터페이스
public interface Tire {
public void roll();
}
// 구현클래스
public class HankookTire implements Tire{
@Override
public void roll() {
System.out.println("한국타이어가 굴러갑니다");
}
}
// 구현클래스
public class KumhoTire implements Tire{
@Override
public void roll() {
System.out.println("금호타이어가 굴러갑니다");
}
}
// 필드 다형성
public class Car {
Tire frontLeftTire = new HankookTire();
Tire frontRightTire = new HankookTire();
void run() {
frontLeftTire.roll();
frontRightTire.roll();
}
}
// 테스트
public class CarExample {
public static void main(String[] args) {
Car mycar = new Car();
mycar.run();
mycar.frontLeftTire = new KumhoTire();
mycar.frontRightTire = new KumhoTire();
mycar.run();
}
}
// 결과
한국타이어가 굴러갑니다
한국타이어가 굴러갑니다
금호타이어가 굴러갑니다
금호타이어가 굴러갑니다
// 매개변수의 인터페이스화
public class Driver {
public void drive(Vehicle vehicle) {
vehicle.run();
}
}
// 인터페이스
public interface Vehicle {
public void run();
}
// 구현 클래스
public class Bus implements Vehicle{
@Override
public void run() {
System.out.println("버스가 달립니다");
}
}
// 구현 클래스
public class Taxi implements Vehicle{
@Override
public void run() {
System.out.println("택시가 달립니다");
}
}
// 매개변수의 다형성 테스트
public class DriverExample {
public static void main(String[] args) {
Driver driver = new Driver();
Bus bus = new Bus();
Taxi taxi = new Taxi();
driver.drive(bus);
driver.drive(taxi);
}
}
// 인터페이스
public interface Vehicle {
public void run();
}
// 구현클래스
public class Bus implements Vehicle{
@Override
public void run() {
System.out.println("버스가 달립니다");
}
public void checkFare() {
System.out.println("승차요금을 체크합니다");
}
}
// 강제타입변환
public class VehicleExample {
public static void main(String[] args) {
Vehicle vehicle = new Bus();
vehicle.run();
//vehicle.checkFare(); <- 인터페이스에 없으므로 실행X
Bus bus = (Bus) vehicle;
bus.run();
bus.checkFare();
}
}
//결과
버스가 달립니다
버스가 달립니다
승차요금을 체크합니다
if (vehicle instanceof Bus) {
Bus bus = (Bus) vehicle
}