2019-02-13
임의의 함수를 만들때, 함수의 인자로 배열을 주게 되면, 해당 함수를 사용할때 해당 인자는 배열로 써야 한다.
마찬가지로 임의의 class를 함수의 인자로 넣었다면, 해당 함수를 사용할때는 해당 class타입의 인자를 써야 한다.
이런 걸 바로 Type Hinting 이라고 한다.

php에서 Type Hinting은 객체, 인터페이스, 배열, callable 에서만 지원하며, 자세한 사항은 아래 링크에서 확인 바란다.
링크 http://qnrdlqkrwhdgns.canxan.com/prob/post/194




삭제 대비용 원본글 복사



#1. Type Hinting의 소개
PHP는 변수 선언이 자유롭고, 타입을 별도로 구분하지 않는 동적타입의 언어다.
동적 타입언어인 PHP지만, 정적 타입언어의 특성을 약간(?) 가지고 있는 부분이 있다. 바로 Type Hinting이다.
Type Hinting으로 함수 인자에서 특정 클래스, 인터페이스 등... 특정 형태만을 받을수 있도록 제한을 걸수 있다.

그렇다고 Type Hinting이 PHP의 모든 변수형태를 지원하는 것은 아니다.
PHP의 기본 변수타입(int, string, float, bool)는 지원하지 않고, 객체/인터페이스/배열/callable 만을 지원한다.
즉, Type Hinting은 객체와 관련된 것임을 알수있다. (실제로 Type Hinting의 카테고리를 보면 'Functions' 카테고리가 아니라 'Classes and Objects'다.)
(왜 객체지향과 Type Hingting이 관련있는지는 뒤에서 살펴본다.)

PHP 메뉴얼의 Type Hinting
http://www.php.net/manual/en/language.oop5.typehinting.php


#2. Type Hinting의 간단한 예제
Type Hinting의 소개를 알아봤으니, 간단한 사용 예제를 보자.

  1. function Func1(MyClass $obj) {
  2. $obj -> test();
  3. }



위와 같은 코드가 있을때, Func1의 첫번째 인자($obj)는 MyClass 클래스(혹은 인터페이스)만을 받을수 있다.
즉, 다음과 같은 코드가 있을 때, YourClass를 사용하는 첫번째 코드는 "Fatal Error: Argument 1 must be an object of class MyClass" 라는 오류가 난다.

예제1:

  1. $o = new YourClass;
  2. Func1($o); // Fatal Error



예제2:

  1. $o = new MyClass;
  2. Func1($o); // $o -> test();



예제1에서 오류가 난 이유는 Func1 함수는 MyClass를 예상했지만, YouClass가 왔기 때문이다.


#3. Type Hinting의 필요성과 객체지향
그렇다면 왜 Type Hinting이 필요하며, 이것이 왜 객체지향과 관련이 있을까?
결론부터 말하자면, '다형성'과 '추상화' 등 인터페이스를 좀 더 언어적으로 지원하기 위함이다.

동적 타입 언어는 개발자가 타입에 대한 책임이 있다.
C언어 등 기타 정적타입언어에서는 int, char 등으로 타입을 명시적으로 선언하는데 반해, PHP에서는 그렇지가 않다. 변수가 타입을 내장하고 있다.
따라서 타입을 알기 위해서는 gettype 같은 함수를 사용해야 한다.

기본 타입은 숫자, 문자, 배열, 진리등 몇가지 없지만 객체의 경우 그 종류에 제한이 없다. 물론 객체형이 object지만, 이것을 말하려는게 아니다. ObjectA가 있을수 있고, ObjectB가 있고... 객체타입은 object 이지만 객체의 종류의 경우 굉장히 많다. 그래서 그중에서 알맞는 클래스와 인터페이스만을 받아들이기 위해 Type Hingting을 사용한다.

물론 get_class나 is_subclass_of 같은 함수들이 있지만, Type Hingting을 통해 좀더 언어적으로 지원하려고 하는 것이다.
BidingTable 인터페이스만을 받는 코드를 살펴보자. BindingTable 인터페이스는 bind 함수를 구현해야한다.

  1. <?php
  2.  
  3. interface BidingTable {
  4. public function bind();
  5. }
  6.  
  7. class Post implements BidingTable {
  8. private $title = '';
  9. private $content = '';
  10. private $author = '';
  11.  
  12. public function bind() {
  13. $db = DBConnection::getConnection();
  14. $db -> execute('insert ... title = '.$this -> title....);
  15. }
  16. }
  17.  
  18. function submitData(BidingTable $data) {
  19. $data -> bind();
  20. }
  21.  
  22. $post = new Post('title1', 'content1', 'author1');
  23. submitData($post);
  24.  
  25. ?>



물론 말도 안되는 억지코드지만, submitData 함수를 보자. BingdingTable 이라는 객체/인터페이스만을 받는다는 뜻이다.
즉, Type Hinting을 통해 개발자는 수많은 클래스와 인터페이스들을 다 뒤적인 필요없이, 필요한 클래스/인터페이스에만 집중하여 개발할수 있다.

Type Hinting이 지원되지 않는다면 다음과 같이 코딩했었어야 했을것이다.

  1. /*
  2. 이 함수의 $data 인자는 BindingData 인터페이스만을 넣어야 합니다.
  3. */
  4. function submitDatas($data) {
  5. if(!($data instanceof BindingData)) return;
  6. $data -> bind();
  7. }



주석과 instanceof 같은 것들을 사용해 BindingData 인터페이스를 사용한다고 명시하는 대신, Type Hinting을 사용함으로써 한결 "깔끔"하게 개발할수 있다는 것이다.
또한 해당 인터페이스나 클래스만을 받아들이니, 다형성과 추상화를 좀더 의미있게 지원할수 있게된다.


#4. 동적타입과 Type Hinting
앞서 Type Hinting의 필요성과 객체지향과의 연관성에 대해서 살펴보았다.
그렇다면 왜 기본 타입(int, string, bool...)에서는 Type Hinting을 지원하지 않는 것일까?

PHP는 타입변환이 자유롭다. 5가 "5"가 될수있고, 5가 true가 될수있다.
또한 "5"가 5, 5.0도 될수있고, true도 될수있다. 심지어 true는 "true"도 될 수 있고, 1이 될수도 있다. 그리고 "Hello!"가 0으로 변환된다.

즉, 타입변환이 동적이기 때문에 별도의 변환에 신경 쓸 필요도 없다. (물론 신경써야할때도 있지만...)
여튼 기본타입에 대해서는 굳이 Type Hinting에 대해 신경을 쓰지 않아도 되고, 만약 타입에 신경을 써야하는 경우를 위해 is_* 함수가 존재한다.


#5. Type Hingting에 대한 오해: Type Hinting은 Type Casting이 아니다.