추상클래스와 비교
- 일반 클래스가 추상 메서드를 갖고 있는 것이 추상 클래스(다른 것도 가질 수 있음)
- ex. 생성자, iv(인스턴스 변수) 등을 가질 수 있다.
BUT,- 인터페이스는 추상 메서드만으로 이루어진 집합. (iv를 가질 수 없음)
- 구현된 것이 아무것도 없다고 생각하면 됨.
interface 인터페이스 이름{
public static final 타입 상수이름 = 값; // 상수 (핵심X) ~ 변수는 안됨!!
public abstract 메서드이름(매개변수목록); // 추상 메서드 (핵심O)
}
interface PlayingCard{
// 항상 public, static, final이다. (생략이 가능함)
public static final int SPADE = 4;
final int DIAMOND = 3; // public static final int DIAMOND = 3;
static int HEART = 2; // public static final int HEART = 2;
int CLOVER = 1; // public static final int CLOVER = 1;
public abstract String getCardNumber();
// public abstract : 생략 가능(항상 인터페이스는 public, abstract이므로)
String getCardKind(); // public abstract String getCardKind();
}
Object
가 최고 조상이 아님.)interface Fightable extends Movable, Attackable{}
interface Movable{
/* 지정된 위치(x, y)로 이동하는 기능의 메서드 */
void move(int x, int y);
}
interface Attackable{
/* 지정된 대상(u)로 공격하는 기능의 메서드 */
void attack(Unit u);
}
class 클래스이름 implements 인터페이스 이름{
// 인터페이스에 정의된 추상 메서드를 모두 구현해야 한다.
}
class Fighter implements Fightable {
public void move(int x, int y) {/* 내용 생략 */}
public void attack(Unit u) {/* 내용 생략 */}
}
abstract
를 꼭 붙여야 한다.abstract class Fighter implements Fightable{
public void move(int x, int y){/* 내용 생략 */}
}
class Fighter extends Unit implements Fightable{
public void move(int x, int y);
public void attack(Fightable f);
}
Unit u = new Fighter();
Fighteable f = new Fighter();
interface Fightable{
void move(int x, int y);
void attack(Fightable f); // Fightable 인터페이스를 구현한 클래스의 인스턴스만 가능
}
Fightable method(){ // Fightable 인터페이스를 구현한 클래스의 인스턴스를 반환
// ...
Fighter f = new Fighter(); // 정확히는 Fighter 클래스의 인스턴스이지만, Fightable로 형변환이 되므로 Fightable로도 반환이 가능하다.(조상 - 자손 관계라 형변환 가능)
return f;
}
Fightable f = method();
package Example;
abstract class Unit {
int x, y;
abstract void move(int x, int y);
void stop() {
System.out.println("멈춥니다.");
}
}
interface Fightable{
void move(int x, int y); // public abstract 생략
void attack(Fightable f); // public abstract 생략
}
class Fighter extends Unit implements Fightable{
public void move(int x, int y){ // 메서드 오버라이딩시 조상보다 접근제어자가 좁으면 안된다.
System.out.println("["+x+","+y+"]로 이동");
}
public void attack(Fightable f){
System.out.println(f+"를 공격");
}
public String toString(){
return "Another Fighter";
}
// 싸울 수 있는 상대를 불러온다.
Fightable getFightable(){ // Fightable 인터페이스를 구현한 클래스의 인스턴스를 반환한다.
Fighter f = new Fighter();
return f;
}
}
public class FighterTest {
public static void main(String[] args) {
Fighter f0 = new Fighter();
Fightable f = new Fighter();
Fightable f2 = f0.getFightable();
// Fightable f3 = f.getFightable(); f가 Fightable 타입이므로 getFightable 메서드 사용 불가
f2.move(777, 1000);
f.move(100, 200);
f.attack(new Fighter());
Unit u = new Fighter();
u.move(300, 200);
u.stop();
}
}
package Example;
public class InterfaceExample {
public static void main(String[] args) {
A a = new A();
a.methodA(new B());
a.methodA(new C());
}
}
class A {
public void methodA(I i) {
i.methodB();
}
}
interface I {
void methodB(); // public abstract 생략
}
class B implements I {
public void methodB() {
System.out.println("methodB()");
}
}
class C implements I{
public void methodB() {
System.out.println("methodB() in C");
}
}
void repair(Repairable r){
if (r instanceof Unit) {
Unit u = (Unit)r;
while(u.hitPoint != u.MAX_HP){
u.hitPoint++;
}
}
}
결론 : 그냥 직접 오버라이딩 하면 우리가 원하는걸 쓸 수 있음.(너무 고민하지 말자.)