Witam
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();
//public 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 ceil();
public function abs();
public function floor();
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?