12. 인터페이스
1. 인터페이스 란
- 일종의 추상 클래스
- 추상메서드와 상수만을 멤버로 가질 수 있다
- 일반메서드나 멤버변수를 가질 수 없다
- 메서드 목록만을 가지고 있다
- 뼈대로만 구성
- 상속받을 클래스가 구현해야 할 기능을 나열
일종의 약속, 최소한의 계약
interface 인터페이스명{}
- 모든 멤버변수는 public static final, 생략가능
- 모든 메서드는 public abstract, 생략가능
2. 인터페이스 구현
- 상속받을 클래스에서
class 클래스명 implements 인터페이스명{}
- extends를 쓰지않고 implements를 쓴다.
interface IAnimal{
public abstract void sound();
void display(); //접근제한자 생략 가능
}
//IAnimal 인터페이스를 구현하는 자식 클래스
class Cat implements IAnimal{
public void sound() {
System.out.println("야옹");
}
public void display() {
System.out.println("cat메서드");
}
}
//IAnimal의 display를 구현하지 않아 추상클래스
abstract class Dog implements IAnimal{
public void sound() {
System.out.println("멍멍");
}
}
class Cow implements IAnimal{
public void sound() {
System.out.println("음메");
}
/*
void display() { //error : 부모메서드를 오버라이딩 할 때 접근제한자는 부모보다 같거나 넓어야 한다
System.out.println("Cow 메서드");
}*/
public void display() {
System.out.println("Cow메서드");
}
}
public class InterfaceTest {
public static void main(String[] args) {
// IAnimal an = new IAnimal(); // error 인터페이스는 객체 생성 불가
Cat c = new Cat();
c.sound();
c.display();
// Dog d = new Dog(); // error 추상클래스 객체 생성 불가
IAnimal an = new Cow();
an.sound();
an.display();
}
}
- 인터페이스의 구현과 부모클래스의 상속 동시 가능
class child extneds fater implements interface{}
class Tv{
public void onTv() {
System.out.println("전원 on");
}
}
interface Computer{
public void dataReceive();
}
//상속과 구현을 동시에
class IPTv extends Tv implements Computer{
public void dataReceive() {
System.out.println("영상 데이터 수신 중");
}
public void powerOn() {
dataReceive();
onTv();
}
}
public class IpTvTest {
public static void main(String[] args) {
IPTv t = new IPTv();
t.powerOn();
}
}
3. 인터페이스 상속
- 인터페이스는 인터페이스만 상속받을 수 있다
- 다중 상속 가능
interface Movable{}
interface Attackable{}
interface Fightable extends Movable, Attackable{}
- 하나의 클래스가 여러개의 인터페이스를 구현할 수 있다
interface TV{}
interface Computer{}
class IPTV implements TV, Computer{}
interface Tv2{
public void onTv();
}
interface Computer2{
public void dataReceive();
}
//인터페이스 다중 상속 가능
class IPTv2 implements Tv2, Computer2{
public void dataReceive() {
System.out.println("영상 데이터 수신 중");
}
public void onTv() {
System.out.println("tv영상 출력");
}
public void powerOn() {
dataReceive();
onTv();
}
}
public class IpTvTest2 {
public static void main(String[] args) {
IPTv2 t = new IPTv2();
t.powerOn();
}
}
- 종합
interface Attackable{
/**
* 지정된 대상을 공격하는 기능
* @param u
*/
public abstract void attack(Unit u);
}
interface Movable{
/**
* 지정된 위치로 이동하는 기능
* @param x
* @param y
*/
void move(int x, int y);
}
//인터페이스끼리의 상속 - extends 사용, 다중상속 가능
interface Fightable extends Attackable, Movable{
}
abstract class Unit{
protected int x, y; //위치
protected int currentHP; //체력
Unit(int x, int y, int currentHP){
this.x = x;
this.y = y;
this.currentHP = currentHP;
}
}
class Fighter extends Unit implements Fightable{
public Fighter(int x, int y, int currentHP) {
super(x,y,currentHP);
}
public void move(int x, int y) {
this.x = x;
this.y = y;
System.out.println(x+","+y+"위치로 이동");
}
public void attack(Unit u) {
System.out.println(u.x+","+u.y+"위치의"+u.currentHP+"체력 유닛 공격");
}
}
public class UnitTest {
public static void main(String[] args) {
Fighter f = new Fighter(10,25,350);
f.move(30,40);
f.attack(new Fighter(30,40,240));
f.move(70, 80);
f.attack(new Fighter(70,80,100));
}
}
4. 인터페이스의 장점
- 표준화가 가능하다
- 인터페이스를 기본 틀로, 일관되고 정형화된 프로그램의 개발 가능
- 관계없는 클래스들에게 관계를 맺어줄 수 있다
- 상속관계도 아닌, 같은 조상을 가지고 있지 않은 클래스도 인터페이스를 통해 공통적으로 구현, 관계 형성 가능
- 독립적인 프로그래밍 가능
- 클래스 간 직접적인 관계를 인터페이스를 통해 간접적인 관계로 변경
- 클래스의 변경이 다른 클래스에게 영향을 미치지 않도록 독립적인 프로그래밍 가능
- ex) 직접적인 관계
/*
* 직접적인 관계의 두 클래스 A,B
* 단점 : 한쪽이 provider 되면 다른쪽도 변경
*/
class A{
/*
public void methodA(B b) {
b.methodB();
}*/
public void methodA(C c) {
c.methodC();
}
}
class B{
public void methodB() {
System.out.println("B클래스 메서드");
}
}
class C{
public void methodC() {
System.out.println("C 클래스 메서드");
}
}
public class InterfaceTest2 {
public static void main(String[] args) {
A a = new A();
//메서드A 호출
//a.methodA(new B());
//c클래스를 추가해 c를 호출하고 싶은 경우
//a클래스의 메서드 구현부를 변경해주어야 한다
a.methodA(new C());
}
}
- ex) 간접적인 관계
/*
* 간접적인 관계의 두 클래스 (A-I-B)
* 클래스 A가 클래스 B를 직접 호출하지 않고 인터페이스를 매개체로 하는 경우
* 클래스A는 인터페이스 I하고만 직접적인 관계에 있기 때문에 클래스B의 변경에
* 영향을 받지 않는다
*/
interface I{
void method();
}
class AA{
public void methodA(I i) {
i.method();
}
}
class BB implements I{
public void method() {
System.out.println("B클래스 메서드");
}
}
class CC implements I{
public void method() {
System.out.println("C클래스 메서드");
}
}
public class InterfaceTest3 {
public static void main(String[] args) {
AA a = new AA();
//methodA()호출
a.methodA(new BB());
//c클래스를 추가해 c를 호출하고 싶은 경우
//a클래스의 메서드 구현부를 변경할 필요 없다
a.methodA(new CC());
}
}
5. 인터페이스 기반의 상수 표현
- 인터페이스 내 변수는 무조건 public static final로 선언되는 특성을 활용
interface Week{
int MON=1, THE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7;
} // 인터페이스 활용
class Week2 {
public static final int MON=1;
public static final int TUE=2;
public static final int WED=3;
public static final int THU=4;
public static final int FRI=5;
public static final int SAT=6;
public static final int SUN=7;
} // 클래스로 선언할 경우
public class InterfaceConst {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("요일 선택:1.월 ~ 7.일");
int type = sc.nextInt();
switch(type) {
case Week.MON :
System.out.println("주간회의");
break;
case Week.THE :
System.out.println("프로젝트 기획 회의");
break;
case Week.WED :
System.out.println("진행사항 보고");
break;
case Week.THU :
System.out.println("사내 축구");
break;
case Week.FRI :
System.out.println("프로젝트 마감");
break;
case Week.SAT :
System.out.println("가족");
break;
case Week.SUN :
System.out.println("휴일");
break;
}
}
}