Zastanawiałem się podczas tworzenia projektu jak rozwiązać problem połączenia metod wywoływanych poprzez __call() z metodami wymaganymi przez interfejs. Otóż zdefiniowałem sobie taki interfejs (chcę ujednolicić swoją kolekcję klas z kategorii działań arytmetycznych;P):
interface MathExp{ public function add(self $b); public function sub(self $b); public function mul(self $b); public function div(self $b); public function __toString(); public function inv(); public function _fileFormat(); private function _extension_exists(); public function fromString(); public function sin(); public function cos(); public function tan(); public function acos(); public function asin(); public function atan(); public function cosh(); public function sinh(); public function tanh(); public function exp(); public function log(); public function log10(); public function mod(self $b); public function pow(self $b); public function sqrt(); public function found(); public function factorial(); public function setScale($scale); public function getScale($scale); }
Zakładam też że wszelkie działania (np. dodawanie) mogą być wykonywane tylko z obiektem należącym właśnie do tego interfejsu. Jak dobrze myślę gdy klasa będzie to implementowała, to będzie musiała zawierać definicję tych metod co prawdopodobnie(jeśli mam rację;P) nie pozwoli na przechwycenie ich przez __call(). Dodatkowo zależy mi na łatwym rozszerzaniu całości bez modyfikacji istniejącego kodu.
Aby zobrazować mój problem wezmę np. metodę add() (dodawanie do siebie dwóch obiektów). Zamierzałem ją zaimplementować w ten sposób:
public function add($b){ if(!is_a($b,"MathExp")) throw new MathExpException(MathExpException::E_INVALID_INTERFACE_STR, MathExpException::E_INVALID_INTERFACE); $specific = "_add_".get_class($b); return $this->$specific($b); }
Jak wiadomo muszę odpowiednio sprecyzować to działanie dla dwóch różnych klas (inaczej doda rzeczywistą do rzeczywistej, zespoloną do zespolonej, rzeczywistą do zespolonej itd.) W związku z tym zamierzałem zrobić do tego w każdej klasie definicję dodawania (prywatną) dla różnych typów argumentu (np. _add_Numbers(), _add_Complex(), _add_Matrix() itp). Powoduje to, że metoda add() jak powyżej. Ale wtedy pojawia się problem powielania kodu, bo dla metody div() postąpię tak samo. Ale nie bez powodu utworzono metodę magiczną __call(), żeby powielać kawałki kodu.
W związku z tym zastanawiam się, czy nie lepiej by było zdefiniować w interfejsie, nie niewiele znaczącej metody add() a zamiast za to kilka metod _add_{class_name}() które będą odpowiadały za operację pomiędzy różnymi typami klas, a metodę add() przechytywać magicznie i wywoływać właśnie metodę dedykowaną dla argumentów?
Dałby radę ktoś podpowiedzieć, ocenić pomysł
