Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Object-oriented programming _ Inheritance vs. interface dla takich samych metod.

Napisany przez: trzczy 12.12.2015, 13:32:56

Kiedy klasy dziedziczące mają takie same metody, to lepiej by dziedziczyły te metody od klasy nadrzędnej, czy miały te metody "przykazane" przez interface i umieszczone w sobie? Takie 2 rozwiązania pokazuję poniżej. Które jest bardziej poprawne?

  1. //example 1
  2. interface Person {
  3. function getName();
  4. function setName($name);
  5. function getHobby();
  6. function setHobby($hobby);
  7. }
  8. class Person2 implements Person{
  9. private $name;
  10. private $hobby;
  11. public function getName()
  12. {
  13. return $this->name;
  14. }
  15. public function setName($name)
  16. {
  17. $this->name = $name;
  18. }
  19. public function getHobby()
  20. {
  21. return $this->hobby;
  22. }
  23. public function setHobby($hobby)
  24. {
  25. $this->hobby = $hobby;
  26. }
  27. }
  28. class Person3 implements Person{
  29. private $name;
  30. private $hobby;
  31. public function getName()
  32. {
  33. return $this->name;
  34. }
  35. public function setName($name)
  36. {
  37. $this->name = $name;
  38. }
  39. public function getHobby()
  40. {
  41. return $this->hobby;
  42. }
  43. public function setHobby($hobby)
  44. {
  45. $this->hobby = $hobby;
  46. }
  47. }
  48. //example 1 end
  49.  
  50. //example 2
  51. abstract class Human{
  52. protected $name;
  53. protected $hobby;
  54. public function getName()
  55. {
  56. return $this->name;
  57. }
  58. public function setName($name)
  59. {
  60. $this->name = $name;
  61. }
  62. public function getHobby()
  63. {
  64. return $this->hobby;
  65. }
  66. public function setHobby($hobby)
  67. {
  68. $this->hobby = $hobby;
  69. }
  70. }
  71. class Human1 extends Human{
  72. protected $name;
  73. protected $hobby;
  74. }
  75. class Human2 extends Human{
  76. protected $name;
  77. protected $hobby;
  78. }
  79. //example 2 end
  80.  
  81. //TESTING
  82. $Mark = new Person2();
  83. $Mark->setName('Mark');
  84. http://www.php.net/echo "{$Mark->getName()}<br>"; //Mark
  85. $Mark = new Human2();
  86. $Mark->setName('Mark');
  87. http://www.php.net/echo "{$Mark->getName()}<br>"; //Mark
  88.  


Z góry dziękuję

Napisany przez: droslaw 12.12.2015, 14:43:14

W przykładzie, który podałeś klasy są identyczne dlatego nie ma sensu ich rozbijać na dwie. Jeśli część metod byłaby wspólna (dokładnie takie same metody łącznie z implementacją), wtedy te metody mogłyby być w klasie nadrzędnej, a w klasach pochodnych umieściłbyś różnice.

W twoim przypadku powinna to być jedna klasa. Czy interfejs byłby tam przydatny to zależy. Można by napisać więcej gdybyśmy znali szerszy kontekst, jaką aplikację piszesz i jak obiekty tej klasy są używane.

Napisany przez: trzczy 12.12.2015, 15:32:26

Cytat(droslaw @ 12.12.2015, 14:43:14 ) *
W przykładzie, który podałeś klasy są identyczne dlatego nie ma sensu ich rozbijać na dwie.

No rzeczywiście.

Kontekst mojego pytania jest taki, że czytam sobie tutorial o design patterns i tam napotkałem na takie "zażądanie" metod w klasie abstrakcyjnej, po czym w klasach dziedziczących zastosowane identyczne metody.

Pomyślałem, że te identyczne metody mogłyby być jedynie dziedziczone z klasy abstrakcyjnej, a nie deklarowane w każdej klasie konkretnej. (Tu w przykładzie zastosowałem interface, a nie klasę abstrakcyjną, co w sumie byłoby chyba analogią). Link do tutoriala: https://wwphp-fb.github.io/faq/object-oriented-programming/design-patterns/abstract-factory/

Definicja klasy abstrakcyjnej wygląda tak:
  1. abstract class AbstractBook {
  2. abstract function getAuthor();
  3. abstract function getTitle();
  4. }


Cały kod tak:
  1. <?php
  2.  
  3. /*
  4.  * BookFactory classes
  5.  */
  6. abstract class AbstractBookFactory {
  7. abstract function makePHPBook();
  8. abstract function makeMySQLBook();
  9. }
  10.  
  11. class OReillyBookFactory extends AbstractBookFactory {
  12. private $context = "OReilly";
  13. function makePHPBook() {
  14. return new OReillyPHPBook;
  15. }
  16. function makeMySQLBook() {
  17. return new OReillyMySQLBook;
  18. }
  19. }
  20.  
  21. class SamsBookFactory extends AbstractBookFactory {
  22. private $context = "Sams";
  23. function makePHPBook() {
  24. return new SamsPHPBook;
  25. }
  26. function makeMySQLBook() {
  27. return new SamsMySQLBook;
  28. }
  29. }
  30.  
  31. /*
  32.  * Book classes
  33.  */
  34. abstract class AbstractBook {
  35. abstract function getAuthor();
  36. abstract function getTitle();
  37. }
  38.  
  39. abstract class AbstractMySQLBook extends AbstractBook {
  40. private $subject = "MySQL";
  41. }
  42.  
  43. class OReillyMySQLBook extends AbstractMySQLBook {
  44. private $author;
  45. private $title;
  46. function __construct() {
  47. $this->author = 'George Reese, Randy Jay Yarger, and Tim King';
  48. $this->title = 'Managing and Using MySQL';
  49. }
  50. function getAuthor() {
  51. return $this->author;
  52. }
  53. function getTitle() {
  54. return $this->title;
  55. }
  56. }
  57.  
  58. class SamsMySQLBook extends AbstractMySQLBook {
  59. private $author;
  60. private $title;
  61. function __construct() {
  62. $this->author = 'Paul Dubois';
  63. $this->title = 'MySQL, 3rd Edition';
  64. }
  65. function getAuthor() {
  66. return $this->author;
  67. }
  68. function getTitle() {
  69. return $this->title;
  70. }
  71. }
  72.  
  73. abstract class AbstractPHPBook extends AbstractBook {
  74. private $subject = "PHP";
  75. }
  76.  
  77. class OReillyPHPBook extends AbstractPHPBook {
  78. private $author;
  79. private $title;
  80. private http://www.php.net/static $oddOrEven = 'odd';
  81. function __construct()
  82. {
  83. //alternate between 2 books
  84. if ('odd' == self::$oddOrEven) {
  85. $this->author = 'Rasmus Lerdorf and Kevin Tatroe';
  86. $this->title = 'Programming PHP';
  87. self::$oddOrEven = 'even';
  88. }
  89. else {
  90. $this->author = 'David Sklar and Adam Trachtenberg';
  91. $this->title = 'PHP Cookbook';
  92. self::$oddOrEven = 'odd';
  93. }
  94. }
  95. function getAuthor() {
  96. return $this->author;
  97. }
  98. function getTitle() {
  99. return $this->title;
  100. }
  101. }
  102.  
  103. class SamsPHPBook extends AbstractPHPBook {
  104. private $author;
  105. private $title;
  106. function __construct() {
  107. //alternate randomly between 2 books
  108. http://www.php.net/mt_srand((double)http://www.php.net/microtime() * 10000000);
  109. $rand_num = http://www.php.net/mt_rand(0, 1);
  110.  
  111. if (1 > $rand_num) {
  112. $this->author = 'George Schlossnagle';
  113. $this->title = 'Advanced PHP Programming';
  114. }
  115. else {
  116. $this->author = 'Christian Wenz';
  117. $this->title = 'PHP Phrasebook';
  118. }
  119. }
  120. function getAuthor() {
  121. return $this->author;
  122. }
  123. function getTitle() {
  124. return $this->title;
  125. }
  126. }

Napisany przez: Fred1485 12.12.2015, 15:41:38

Tak moimi słowami, klasę abstrakcyjną czy interfejs piszę często po to, aby mieć pewność, że dany obiekt posiada implementację danej metody.
Przykładowo masz np. klasę abstrakcyjną Storage obsługującą zapisywanie danych, po której dziedziczą np. klasy Database, Session, File itp. Każda z nich musi mieć metodę odczytującą i zapisującą. Więc w klasie nadrzędnej Storage umieszczam dwie metody write i read. Potem gdy, inna klasa będzie musiała przyjąć obiekt danych, to w metodzie rzutuję

  1. function przyjmij(Storage $storage) {//}
I mam pewność że będę mógł odczytać i zapisać dane. Przykład taki z rękawa, może wiesz co mam na myśli.

Napisany przez: Comandeer 12.12.2015, 19:00:55

Osobiście spotkałem się z podejściem, gdzie interfejsy służyły do zdefiniowania publicznego API konkretnej klasy obiektów (np Storage), natomiast klasa abstrakcyjna była podstawową implementacją tego interfejsu, zawężając jego zakres do podklasy tych obiektów (np DBStorage). Po tej klasie dziedziczyły już konkretne klasy, zmieniając jedynie to, co trzeba (np MySQLStorage).

Napisany przez: trzczy 12.12.2015, 22:37:35

Dzięki za odpowiedzi. Dla mnie wynika z tego, że nie ma "lepszego" sposobu, i wybór należy do programisty. Albo pokazuje on w klasie nadrzędnej lub interfejsie, jakie metody będą wymagane w kasach dziedziczących względnie implementujących interfejs, albo kieruje się rozsądkiem i stosuje dziedziczenie identycznych metod zamiast je powielać.
Oczywiście metoda 1. ma też swoje zalety, bo kod jest wtedy czytelniejszy.

Napisany przez: Damonsson 13.12.2015, 00:36:28

To nie jest kwestia żadnego wyboru. Do czego innego służy interfejs, a do czego innego klasa abstrakcyjna. I nie masz tu żadnego wyboru, czy jeszcze lepiej "lepszego rozwiązania".

W interfejsach umieszczasz informację o tym jakie metody muszą być zawarte w klasie, która go implementuje i tyle, mogą to być zupełnie nie powiązane ze sobą klasy, które implementują ten sam interfejs. Na dodatek interfejs nie może zawierać żadnej funkcjonalności.

Klasa abstrakcyjna, może mieć jakąś funkcjonalność w sobie, a resztę zostawia klasom dziedziczącym po niej. Na dodatek każda klasa dziedzicząca, musi mieć z nią dość ścisły związek.

Podsumowując implementacja i dziedziczenie są od siebie niezależne i nic nie stoi na przeszkodzie, implementować interfejs i dziedziczyć po danej klasie jednocześnie. Czy też tylko implementować interfejs, czy też tylko dziedziczyć po klasie abstrakcyjnej.

Twój abstrakcyjny przykład jest bez sensu i nie rozumiesz idei obiektowości. Przykład z tutoriala jest sensowny, mógłbyś sobie do niego jeszcze napisać interfejsy i byłoby też dobrze, niektórzy powiedzą, że nawet lepiej.

Napisany przez: trzczy 13.12.2015, 01:07:19

Damonsson, nie rozumiesz pytania. Chodzi o dublowanie metod. W tutorialu metody są dublowane, a można tego tego uniknąć przez dziedziczenie tych metod z klasy nadrzędnej. Nie chodzi mi o róznice między abstract class a interface, bo jest mi dobrze znana. Z dyskusji powyżej wynika, że programista sam decyduje, czy lepiej będzie uzyskać czytelność kodu przez zastosowanie abstract class lub interface, czy zastosować dziedziczenie metod i uniknąć dublowania.

Napisany przez: viking 13.12.2015, 10:42:44

Ale Damansson dobrze Ci odpowiedział i według mnie nie zrozumialeś do końca jego wypowiedzi. Nijak się ma dublowanie metod bo w interface jest tylko ich czysta definicja. Klasa abstrakcyjna może zawierać część funkcjonalności wspólną dla wszystkich klas potomnych ale to do klas poszczególnych zależy jak te specyficzne metody (abstrakcyjne) obsłużą. Masz jeszcze cechy (traits) o których tu nic nie mówisz a które możesz dołączyć do kodu również eliminując powielanie.

Zobacz też interface w takim kontekście: https://github.com/RalfEggert/zend-expressive-tutorial/blob/part6/src/Album/Action/AlbumCreateFactory.php

Napisany przez: trzczy 13.12.2015, 18:42:16

Cytat(viking @ 13.12.2015, 10:42:44 ) *
Ale Damansson dobrze Ci odpowiedział i według mnie nie zrozumialeś do końca jego wypowiedzi.
Nie odpowiedział na moje pytanie. Jego wypowiedź zrozumiałem, aleta wypowiedź nie uczyniła mnie bogatszym w wiedzę, ani nie odpowiedziała na problem.

Cytat(viking @ 13.12.2015, 10:42:44 ) *
Nijak się ma dublowanie metod bo w interface jest tylko ich czysta definicja.

W interface nie ma definicji metod. Są nazwy metod.

Cytat(viking @ 13.12.2015, 10:42:44 ) *
Klasa abstrakcyjna może zawierać część funkcjonalności wspólną dla wszystkich klas potomnych ale to do klas poszczególnych zależy jak te specyficzne metody (abstrakcyjne) obsłużą.
Nie pytam o to, co to jest klasa abstrakcyjna, bo wiem jak ona działa.

Słuchajcie, ja nie pytam, co mogę jeszcze zrobić, jak ten tutorial pozmieniać itp. Powtarzam pytanie. Czy powielanie definicji metod w klasach podrzędnych, we wskazanym tutorialu, można uznać za wadę tego kodu, w świetle tego, że można takie identyczne definicje metod dziedziczyć z klasy nadrzędnej.

Po prostu, wydaje mi się, że w informatyce jednak nie powinno się powielać tego samego kodu.

Napisany przez: Comandeer 13.12.2015, 18:53:29

Cytat
W interface nie ma definicji metod. Są nazwy metod.

Czyli są definicje… To, co jest w klasie abstrakcyjnej (oczywiście jeśli metody mają ciało), to już implementacja, nie definicja.

Co do kodu w tutorialu: osobiście zamieniłbym tę klasę abstrakcyjną na interfejs, jeśli i tak nie podaję podstawowej implementacji tych metod.

Napisany przez: Pyton_000 13.12.2015, 19:08:52

O jakim dublowaniu mówisz. Bo tutaj jedynie dublowanie gettery.

Jeśli jednak pisząc ogólnie to:

klasa nadrzędna zawsze powinna zawierać zestaw metod wspólnych.
Czy to będzie klasa abstract czy zwyczajna to już zależy od preferencji.
Czy paretn ma być implements Intreface to też zależy.

Inny przypadek to jak ktoś wcześniej napisał Interface jako definicja metod (Przytoczony przykład z Storage).

Napisany przez: droslaw 13.12.2015, 22:18:07

trzczy, Damansson ma rację, w tutorialu żadne metody nie są dublowane. Wydaje się, że rzeczywiście nie zrozumiałeś jeszcze dobrze programowanie obiektowego.

AbstractFactory jest interfejsem czyli nie posiada implementacji. Zawiera tylko deklarację metod (deklarację nie definicję bo definicja to implementacja metody).
Każda klasa implementująca interfejs AbstractFactory definiuje metody zadeklarowane w tym interfejsie, ale nie jest to duplikacja. Dzięki temu masz dwie różne implementacje tego samego interfejsu. To znaczy możesz używać obiektu dowolnej z klas pochodnych w dokładnie ten sam sposób, chociaż każda klasa będzie zachowywać się trochę inaczej (czyli korzystasz z polimorfizmu).

Zaleta tego jest taka, że kod który używa obiektu dowolnej z klas implementujących ten interfejs nie musi brać pod uwagę, z jaką klasą konkretnie ma do czynienia. Kod przez to będzie prostszy w zrozumieniu, rozbudowie i testowaniu.

Ktoś u góry podawał już przykład z klasą Storage. Powiedzmy że tworzysz aplikację, która zapisuje jakieś wiadomości do plików lub bazy.

Kod nie był testowany i może zawierać błędy.

  1. <?php
  2.  
  3. interface StorageInterface
  4. {
  5. public function save($message);
  6. }
  7.  
  8. class FileStorage implements StorageInterface
  9. {
  10. private $dirPath;
  11.  
  12. public function __construct($dirPath)
  13. {
  14. $this->dirPath = $dirPath; // ustawiasz katalog(folder) w jakim zapisywać pliki
  15. }
  16. public function save($message)
  17. {
  18. // tu masz kod zapisujący do pliku
  19. }
  20. }
  21.  
  22. class DbStorage implements StorageInterface
  23. {
  24. public function __construct($dbName, $userName, $passwd, $host)
  25. {
  26. // tu łączymy się z bazą
  27. $this->conn = connect_some_db($dbName, $userName, $passwd, $host);
  28. }
  29.  
  30. public function save($message)
  31. {
  32. // tu zapisujemy do bazy
  33. }
  34. }
  35.  
  36. abstract class AbstractRequestHandler
  37. {
  38. protected $storage;
  39.  
  40. public function __construct(StorageInterface storage)
  41. {
  42. $this->storage = storage;
  43. }
  44.  
  45. abstract public function handleRequest(Request $request);
  46. }
  47.  
  48. class ARequestHandler extends AbstractRequestHandler
  49. {
  50. public function handleRequest(Request $request)
  51. {
  52. // tu pobieramy dane z requesta, generujemy wiadomość
  53. // i zapisujemy
  54. $this->storage->save($message);
  55. }
  56. }
  57.  
  58. class BRequestHandler extends AbstractRequestHandler
  59. {
  60. public function handleRequest(Request $request)
  61. {
  62. // tu pobieramy dane z requesta
  63. // generujemy wiadomość w zupełnie inny sposób niż w klasie ARequestHandler
  64. // i zapisujemy
  65. $this->storage->save($message);
  66. }
  67. }
  68.  


  1. <?php
  2.  
  3. // ... tu mamy trochę kodu, tworzymy obiekt Request itp.
  4. $storage = FileStorage('messages/');
  5. $requestHandler = ARequestHandler($storage);
  6. $requestHandler->handleRequest($request);
  7.  


Ten przykład pokazuje, jak łatwo można zmieniać sposób zapisu wiadomości w aplikacji. Wystarczy zmienić jedną linijkę (stworzyć obiekt klasy DbStorage zamiast FileStorage), a obiekty RequestHandler będą zapisywać wiadomości do bazy danych zamiast do plików. Chcesz zmienić sposób generowania wiadomości? Znowu zmieniasz jedną linijkę ARequestHandler na BRequestHandler.

Obiekty StorageInterface i AbstractRequestHandler możesz tworzyć np. na podstawie pliku konfiguracyjnego przy stracie aplikacji i dalej nie obchodzi Cie z jakiej implementacji korzystasz. Przez to możesz zmieniać zachowanie aplikacji w pliku konfiguracyjnym.

Klasa zajmująca się zapisem do bazy jest interfejsem, ponieważ jedyną wspólną rzeczą dla wszystkich klas zapisujących wiadomości jest to, że aby zapisać wiadomość trzeba wywołać metodą save z jednym argumentem(php 5.x niestety nie pozwala ograniczyć typu argumentu do stringa w deklaracji metody). AbstractRequestHandler jest klasą abstrakcyjną, ponieważ jej klasy pochodne mają wspólny kod (konstruktor).

Zauważ że sposób zapisu i sposób generowania wiadomości zmieniasz niezależnie, dzięki temu że wydzieliliśmy te dwie odpowiedzialności od siebie. Gorszym rozwiązaniem byłoby definiowanie sposobu generowania wiadomości i zapisu w jednej klasie, wtedy moglibyśmy mieć klasy ARequestHandlerFileStorage, ARequestHandlerDbStorage, BRequestHandlerFileStorage itd.

Zanim zacznie się uczyć wzorców projektowych, warto dowiedzieć się trochę na temat ogólnych zasad programowania obiektowego albo kupić dobrą książkę na temat wzorców. W internecie nigdy nie trafiłem na źródła z dobrym wprowadzeniem do programowanie obiektowego, nigdy też nie widziałem w internecie dobrych przykładów.

Jeszcze co do interfejsów: http://koziolekweb.pl/2009/11/16/s-o-l-i-d-ne-programowanie-%E2%80%93-czesc-4-czyli-apartheid/ przykłady są w javie ale każdy powinien zrozumieć.

Napisany przez: trzczy 14.12.2015, 08:28:08

Cytat(Pyton_000 @ 13.12.2015, 19:08:52 ) *
O jakim dublowaniu mówisz. Bo tutaj jedynie dublowanie gettery.

Mówię konkretnie o tym właśnie dublowaniu.

Cytat(droslaw @ 13.12.2015, 22:18:07 ) *
Damansson ma rację, w tutorialu żadne metody nie są dublowane.

Zdaje się, że 2 osoby zauważyły, że są dublowane.

I pojawia się nam problem, co to znaczy definicja metody. Dla mnie definicja metody to jest to samo co deklaracja metody. I z tego co widzę, to sugerujecie, że definicją metody jest na przykład samo coś takiego:
  1. public function save($message);


Zatem mielibyśmy definicję metody, która nie określa, jak działa metoda, czyli nie definiuje metody w sensie matematycznym. Jest to dla mnie trudne do przyjęcia, i w sumie nie wiem co z tym zrobić. Pamiętam, że kiedyś coś kodowałem w jakimś języku programowania, gdzie było słowo kluczowe 'defun nazwafunkcji' i dalej następowało body funkcji. Ale jeśli w oop rzeczywiście definicja nie musi definiować, to może niepotrzebnie poprawiałem Kolegę powyżej w jednym z postów.

Nie będę się szczegółowo odnosił do wszystkiego w tym wątku, ale ogólnie pojawia mi się obraz i wnioski, za co Wam dziękuję.

Napisany przez: Pyton_000 14.12.2015, 08:33:13

Settery i gettery to nie problem. O ile nie mają std. zadania to prawie każde IDE wygeneruje Ci taką listę.

Ad. definicji w programowaniu jest definicja/deklaracja i implementacja.


Napisany przez: droslaw 14.12.2015, 12:16:07

Cytat(trzczy @ 14.12.2015, 08:28:08 ) *
I pojawia się nam problem, co to znaczy definicja metody. Dla mnie definicja metody to jest to samo co deklaracja metody. I z tego co widzę, to sugerujecie, że definicją metody jest na przykład samo coś takiego:
  1. public function save($message);

Kiedyś bawiłem się w C++, tam rozróżnienie miedzy definicją i deklaracją jest wyraźne: http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration. Java: http://stackoverflow.com/questions/11715485/what-is-the-difference-between-declaration-and-definition-in-java (PHP jest pod tym względem podobny do Javy). Dlatego dla mnie deklaracja to nie koniecznie definicja. A może lepiej używać pojęć interfejs i implementacja. Warto byłoby ustalić wspólne nazewnictwo bo wtedy będzie mniej nieporozumień i chętnie dowiem się co jeszcze inni na ten temat myślą.

Cytat(trzczy @ 14.12.2015, 08:28:08 ) *
Zatem mielibyśmy definicję metody, która nie określa, jak działa metoda, czyli nie definiuje metody w sensie matematycznym. Jest to dla mnie trudne do przyjęcia, i w sumie nie wiem co z tym zrobić. Pamiętam, że kiedyś coś kodowałem w jakimś języku programowania, gdzie było słowo kluczowe 'defun nazwafunkcji' i dalej następowało body funkcji. Ale jeśli w oop rzeczywiście definicja nie musi definiować, to może niepotrzebnie poprawiałem Kolegę powyżej w jednym z postów.

Czyli w interfejsie masz metody bez implementacji a implementację dajesz dopiero klasach implementujących ten interfejs. Jest to jedna z najważniejszych cech programowania obiektowego. Dobrze że uczysz się wzorców ale lepiej byłoby gdybyś najpierw dobrze zrozumiał ogólne zasady dotyczące programowania obiektowego.

Napisany przez: Matrix12 15.12.2015, 08:00:27

W przykładzie gdzie implementujesz interfejs chodzi o to, że w interfejsie masz określone jakie metody musza być implementowane w danym obiekcie. W Twoim przykładzie pokazałeś dwa obiekty implementujące ten interfejs, a te obiekty są różne to że one zawierają te metody to nie oznacza że są identyczne, bo poniżej mogą zawierać inne metody które coś tam robią. Interfejs określa Ci czego potrzebujesz aby stworzyć dany obiekt który np. będzie wstrzykiwany do innej metody lub obiektu i wtedy będziesz miał wpisane na przykład tak :


public function example(TwojInterfejs $service){ .. }


Napisany przez: trzczy 17.12.2015, 01:13:47

Jeszcze się gubię w tym branżowym słownictwie...

Cytat(Matrix12 @ 15.12.2015, 08:00:27 ) *
public function example(TwojInterfejs $service){ .. }


TwojInterfejs to jest type hinting i jednocześnie nazwa wymaganej klasy? Słowa 'Interfejs' używacie w znaczeniu 'interface', czyli słowa kluczowego php czy może w znaczeniu API? Sorka pewnie kaleczę zwyczajowy żargon. sciana.gif

Napisany przez: Pyton_000 17.12.2015, 10:06:18

Możesz nazwać jak chcesz np:

StorageInterface
StorageI
IStorage
InterfaceStorage

Dowolność, chodzi o to żeby wiedzieć że Obiekt docelowy wkładany do metody musi być typu lub implementować interface.

Napisany przez: trzczy 17.12.2015, 12:35:52

Cytat(Pyton_000 @ 17.12.2015, 10:06:18 ) *
Dowolność, chodzi o to żeby wiedzieć że Obiekt docelowy wkładany do metody musi być typu lub implementować interface.

Zatem przykładowo taki type hint 'InterfaceStorage' musi być wcześniej zadeklarowany w ten sposób:

class InterfaceStorage {
//some code here
}

lub

interface InterfaceStorage {
//some code here
}

tak łopatologicznie?

Napisany przez: Pyton_000 17.12.2015, 12:37:16

tak, tylko weź pod uwagę to że samego Interface nie możesz przekazać jako parametr. Zawsze to musi być klasa która implementuje dany typ lub rozszerza lub nim jest.

Napisany przez: viking 17.12.2015, 12:50:28

Nie było przypadkiem w którymś PSR że interface ma być przyrostkiem? Czyli StorageInterface.

Napisany przez: Pyton_000 17.12.2015, 14:01:21

Było smile.gif

https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)