[PHP] interface (그것은 약속이니까)

항해자·2023년 4월 8일
0

PHP

목록 보기
3/3

인터페이스는 추상클래스와 유사한 개념이지만, 추상클래스와 달리 구현부가 없는 메소드들로 이루어져 있습니다. 즉, 인터페이스는 구현부가 없는 메소드를 선언하는 일종의 약속으로 볼 수 있습니다.

인터페이스는 어떻게 선언하나요?

인터페이스를 선언할 때는 interface 키워드를 사용합니다. 인터페이스 내부에서는 사용할 메소드의 '선언' 만 가능하며 내용의 구현을 하지 않습니다.

interface MyInterface {
    public function method1();
    public function method2($param);
}

인터페이스를 구현하기

인터페이스는 implements키워드를 통해 클래스에서 구현이 가능합니다. 이때 인터페이스를 구현할 클래스는 반드시,
해당 인터페이스내의 모든 메소드를 반드시 구현해야 합니다.

//여기서 인터페이스를 구현하고,
interface MyInterface {
    public function method1();
    public function method2($param);
}

//이렇게 다른 클래스에서 implements로 받아서 구현
class MyClass implements MyInterface {
    public function method1() {
        // 메소드1의 구현
    }

    public function method2($param) {
        // 메소드2의 구현
    }
}

이처럼 상속받은 클래스에서 구현한 내용이 부모 클래스의 메소드를 덮어 쓰는것을 오버라이딩 overriding이라고 합니다.

인터페이스는 어떤 장점이 있을까요?
세가지만 살펴보겠습니다.

1. 다중 상속이 가능합니다.

하나의 클래스가 여러개의 인터페이스를 구현할 수 있습니다.
예를 들어 달리기/걷기, 공격/방어 모두 할 수 있는 '전사'와 '도적' 클래스를 다중 상속을 사용해 구현한다면 아래와 같이 전투 스킬을 정의한 CombatSkills와 이동 스킬을 정의한 MovementSkills 인터페이스들을 모두 상속 받을 수 있습니다.

//전투 스킬
interface CombatSkills {
    public function attack();
    
    public function defense();
}

//아동 스킬
interface MovementSkills {
    public function run();
    
    public function walk();
}

//전사
class Warrior implements CombatSkills, MovementSkills {
    public function attack() {
        //공격 구현
    }

    public function defense() {
        //방어 구현
    }
    
    public function run() {
        //달리기 구현
    }
    
    public function walk() {
        //걷기 구현
    }    
}

//도적
class Thief implements CombatSkills, MovementSkills {
    public function attack() {
        //공격 구현
    }

    public function defense() {
        //방어 구현
    }
    
    public function run() {
        //달리기 구현
    }
    
    public function walk() {
        //걷기 구현
    }    
}

2. 유연한 구조
인터페이스는 구현내용이 없는 메소드를 선언하므로, 이를 상속받은 클래스에서 구체적인 메소드 내용을 구현할 수 있습니다.
즉 필요한 메소드는 반드시 포함하게하되, 구현은 자유롭게 확장할 수 있도록 설계가 가능합니다.
CombatSkills 인터페이스에 물리공격과 마법공격이 있고, 이 인터페이스를 전사와 마법사가 상속받는 경우 아래와 같이, 각 클래스별로 메소드의 내용을 다르게 구현할 수 있습니다.

interface CombatSkills {
    public function physicalAttack();
    public function magicAttack();
}

//전사
class Warrior implements CombatSkills {
    public function physicalAttack() {
        return "무기 휘두르기!";
    }
    
    public function magicAttack() {
        // 마법공격불가능
        return false;
    }
}

//마법사
class Wizard implements CombatSkills {
    public function physicalAttack() {
        // 물리공격불가능
        return false;
    }
    
    public function magicAttack() {
        return "파이어볼~!";
    }
}

3. 코드의 일관성 보장
인터페이스를 상속받았다면, 클래스안에서 인터페이스내의 모든 메소드를 반드시 구현해야합니다.
또한 만약 인터페이스내 메소드의 파라미터에 데이터 타입 힌트가 선언되었다면 함께 구현할 클래스에서도 동일하게 선언해야 합니다.

//전투 스킬
interface CombatSkills {
    public function physicalAttack(string $target); //파라미터로 문자열 $target 사용
    public function magicAttack(array $targets); //파라미터로 배열 $targets 사용
}

//마법전사
class magicWarrior implements CombatSkills {
    public function physicalAttack(string $target) {
        return "무기 휘두르기!";
    }
    
    public function magicAttack(array $targets) {        
        return "파이어볼!!";
    }
}

결국 인터페이스는 구현은 자유롭게 하되, 반드시 메소드를 선언해야한다는 약속의 개념이 강합니다.

실무에선 어떻게 사용할 수 있을까요?

여러사람이 협업을 통해 개발을 진행할 때, 프로젝트가 규모가 점점 방대해질때 인터페이스를 사용하거나 도입한다면 일관된 구조를 유지하기에 매우 용이합니다.

또한 새로운 클래스의 추가가 필요할때도, 인터페이스를 사용하면 기존 코드를 수정할 필요 없이 추가할 수 있습니다.
필요한 클래스에서 상속만 받으면 되니까요.

profile
웹개발자

0개의 댓글