36. Interface - 1. 소개
규제를 통한 자유
마지막 줄 뜻:
콘크리트(구체적인) 클래스는 컨트랙트(계약) 인터페이스에 정의되어 있는 메소드를
반드시 implement=구현해야 한다.
만약 그 메소드가 없다면
이 프로그램은 실행되지 않는다.
콘크리트 클래스를 만들건데,
얘가 꼭 프라미스 메소드를 갖도록 하고 싶다면,
컨트랙트 인터페이스를 정의하면 된다.
그리고 프라미스 메소드는 반드시 하나의 인자를 가져야 한다.
extends가 아니고 implements이다.
실행시키면 호출한 적도 없는데 에러가 뜬다.
$param은 반드시 배열로 해라.
리턴 값은 반드시 숫자로 해라.
복수의 인터페이스를 구현하게 할 수도 있다.
cf) 상속은 1개 밖에 안 된다.
36. Interface - 2. 사례(1) 협업의 사례
협업할 때 전달
나는 compare라는 메소드가 필요하고
그 메소드는 두 개의 인자를 필요로 하고
각각의 인자는 문자이고
리턴값은 불리언이다.
앞에 public도 붙여준다.
그리고 나서 이 컨트랙트 인터페이스를 구현한 Dummy(가짜) 클래스를 만든다.
그러면 협업하는 사람은 콘크리트 클래스를 만들어서 compare라는 메소드를 만들고
완성이 되면 우리한테 인계할 것이다.
그러면 우리는 콘크리트 클래스로 더미 클래스를 대체하면
그러면 콘크리트 클래스는 똑같이 compare라고 하는 메소드의
입력값과 출력값, 인자와 리턴값을 구현했기 때문에
이게 여기에 탁 붙으면 다른 코드들과 완벽하게 잘 맞게 될 것이다.
즉 인터페이스는 사회적인 계약이라고 볼 수 있다.
36. Interface - 3. 사례(2) Monolog의 사례
Monolog는
Logger라는 클래스를 인스턴스화시키면
Monolog 인스턴스가 만들어지고
$log 인스턴스의 워닝을 하게 되면
EGO라는 워닝 메시지를 발생시킨다.
에러라고 하면 ING라는 에러 메시지를 발생시킨다.
이 각각의 메시지들을 어떻게 가공할 것인가를 결정하는 것이
pushhandler이다.
여기에 StreamHandler라는 클래스에
현재 디렉토리의 app.log라는 파일을 주면
app.log라는 파일에
EGO와 ING가 뜬다.
맨 뒤에 level: Logger::Warning은
Logger 클래스에 static property(static 변수)인 Warning을 주게 되면
Warning이나 Warning보다 더 심각한 경우에 로깅을 한다는 뜻이다.
Warning보다 error가 더 심각하기 때문에
두 개는 다 화면에 찍힌다는 뜻이다.
만약에 level: Logger::Warning를
level: Logger::ERROR로 바꾸면
이번에는 ERROR만 떴다.
∵ ERROR보다 심각한 경우에만 출력하게 했으니까
NativeMailerHandler를 클릭해보면
얘를 쓰려면 네임 스페이스가
Monolog\Handler에 있는
NativeMailerHandler를 쓰면 된다고 나와있다.
use와 $log의 마지막 줄을 추가했다.
이렇게 하면 로그가 발생했을 때
파일로 기록도 하면서
메일도 보내줄 수 있다.
메일 주소랑 주소 등등 줄바꿈하고
마지막줄에 level: Logger::EMERGENCY라고 쓰고
제일 마지막 줄을 추가했다.
이것은 EMERGENCY(긴급상황)가 발생했을 때
app.log에도 기록하겠지만 메일로도 보내겠다는 것이다.
EMERGENCY가 에러나 워닝보다 우선순위가 높기 때문에
EMERGENCY에만 적용된다.
다시 수업의 주제로 돌아와서
pushHandler라는 메소드는
StreamHandler와 NativeMailerHandler라는 서로 다른 클래스를 받고 있는데
그것이 가능한 이유가 뭘까?
아울렛과 플러그를 서로 다른 제조사가 만들어도
완벽하게 결합되는 것과 같은 이치이다.
그 주인공은 인터페이스이다.
pushHandler라는 메소드를 클릭해서
메소드에 대한 구현체로 들어왔다.
Logger라는 클래스의 pushHandler로 순간이동을 한 것이다.
pushHandler라는 메소드에는
타입 핀트(?)로
$handler라는 변수는 반드시 HandlerInterface여야 한다고 되어 있다.
즉, HandlerInterface라는 타입 핀트는
여기로 들어오는 클래스가 반드시 HandlerInterface를 구현하고 있어야 한다고 강제하고 있다.
그렇기 때문에 pushHandler 안에서 사용되는 코드들은
$handler를 통해서 유입된 클래스가
반드시 HandlerInterface라는 인터페이스에 정의된 메소드를 갖고 있을 것이고
그 메소드들을 약속된 형식에 따라서 추출하면 잘 동작할 것이라고
안심하고 사용할 수 있다.
StreamHandler라는 클래스는 HandlerInterface를 구현하고 있을 것이라고 예상했는데
안 보이고
대신 AbstractProcessingHandler라는 클래스를 상속받고 있다.
이게 뭔지 클릭해서 들어가보자.
얘는 또 AbstractHandler를 상속받고 있다.
다시 얘로 들어가보니까 AbstractHandler는
드디어 HandlerInterface를 구현하고 있다는 사실을 알게 되었다.
다시 돌아와서,
pushHandler라는 메소드는
StreamHandler와 NativeMailerHandler라는 서로 다른 클래스를 받고 있는데
그것이 가능한 이유는
아울렛과 플러그를 서로 다른 제조사가 만들어도
완벽하게 결합되는 것과 같은 이치이다.
그 주인공은 인터페이스이다.
pushHandler라는 메소드를 클릭해서
메소드에 대한 구현체로 들어가보자.
pushHandler라는 메소드에는
타입 핀트로
$handler라는 변수는 반드시 HandlerInterface여야 한다고 되어 있다.
즉 HandlerInterface라는 타입 핀트는
여기로 들어오는 클래스가 반드시 HandlerInterface를 구현하고 있어야 한다고 강제하고 있는 것이다.
그렇기 때문에 pushhandler 안에서 사용되는 코드들은
$handler를 통해서 유입된 클래스가
반드시 HandlerInterface라는 인터페이스에 정의된 메소드를 가지고 있을 것이고,
그 메소드들을 약속된 형식에 따라서 호출하면 잘 동작할 것이라고
안심하고 사용할 수 있는 것이다.
이번에는 StreamHandler와 NativeMailerHandler가 어떻게 생겼는지 보자.
StreamHandler라는 클래스
'PHP > 생활코딩' 카테고리의 다른 글
6/1(4) 생활코딩 - PHP 기본수업 - abstract < PHP 完 > (0) | 2020.06.01 |
---|---|
6/1(2) 생활코딩 - PHP 기본수업 - 상속 (0) | 2020.06.01 |
6/1 생활코딩 - PHP 기본 수업 - 컴포저 (0) | 2020.06.01 |
5/31(5) 생활코딩 (0) | 2020.05.31 |
5/31(3) 생활코딩 (0) | 2020.05.31 |
댓글