I'm trying to create a PHP file that calls a function in another file. Some sample code:
Interface code:
interface AJAXDispatcher {
static function dispatch($action);
}
Implementation:
class myAJAX implements AJAXDispatcher {
static function dispatch($action) {
if ($action === "action1") {
do_something();
}
This seems ok to me. I try to call it by first importing the file that it's in. I'm trying to make it independent of the name of the class so that I can do something like this:
AJAXDispatcher::dispatch($action);
Thought this would work as myAJAX would inherit from AJAXDispatcher, but I get the following error:
Fatal error: Cannot call abstract method AJAXDispatcher::dispatch() in ....
Anyone know what I'm doing wrong?
Interfaces with static methods don't make any sense, because to call a static method you (usually) need to know the class name.
Instead, you should make the method non-static and create an instance of myAJAX somewhere. The code that calls the AJAXDispatcher receives the instance and calls it. You can use type hinting to ensure you are getting the right instance.
interface AJAXDispatcher {
public function dispatch($action);
}
class myAJAX implements AJAXDispatcher {
public function dispatch($action) {
do_something();
}
}
class Controller {
private $dispatcher;
public function __construct(AJAXDispatcher $dispatcher) {
$this->dispatcher = $dispatcher;
}
public function action($action) {
$this->dispatcher->dispatch($action);
}
}
$dispatcher = new myAJAX();
$controller = new Controller($dispatcher);
$controller->action('index');
This example uses the Dependency Injection design pattern.
An interface has no method implementation. It only defines a public API that classes have to implement. How they implement it, is up to the concrete classes. Thus, you cannot call methods of an interface directly, because there is no code to call. You have to call the method on the implementing class.
Have a look at the PHP Manual on Interfaces.
No, you can't do that. There are several things wrong here
That's now how inheritance works. Method chaining goes up the class hierarchy, now down.
Static methods are connected to the class. If you override a static method in a subclass, and want to invoke the subclass' version, you must reference the subclass explicitly.
Interfaces have no implementation. Even if the language allowed the type of call you're making, nothing would happen. AJAXDispatcher::dispatch() has no body.
You're going to have to re-think your strategy here.
Related
I have an abstract class that has a method which uses a static function. This static function is defined in sub-classes and is different for each sub-class. Which sub-class will be used to create object is determined in the script. See super simplified code below:
abstract class fooClass implements iFooClass {
function getBar(){
$bar = self::getSomething();
return $bar;
}
}
interface iFooClass{
static function getSomething();
}
class fooSubClass_A extends fooClass {
static function getSomething() {
//do something;
//return something;
}
}
class fooSubClass_B extends fooClass {
static function getSomething() {
//do something else;
//return something else;
}
}
$foo = New fooSubClass_A;
$bar = $foo->getBar();
This code gives me this error:
Fatal error: Cannot call abstract method iFooClass::getSomething() in C:\wamp\www\Classes\fooClass.php on line 12
I thought since the sub-classes have access to super-classes method getBar it would be called from the sub-class and thus have access to its static function. Apparently not. Is there a way to redo this to make it work?
I think at first you should implement "getSomething" method from "iFooClass" interface in "fooClass" because all interface functions must be implemented in child class, that's the basic rule of interfaces. Only after that you can include this function into another class method.
Edit: Abstract classes have ability not to implement all interface methods, if they are implemented in it's subclasses.
Edit2 When you call method with Self keyword, it calls method from class where "SELF" actually exists and not from class object from which we are calling method. That's why self::method() should be changed with static::method()
I want to disable a class to be instantized by new operator, but lets suppose a getObject method what creates and returns an instance of it. Is it doable?
class C
{
protected function __construct()
{
}
public static function getObject()
{
return new self();
}
}
UPDATE:
The code above fulfills the requirement: the class cannot be instantiated using new, one needs to use the factory method getObject() to create an object. However, the OP did not specify the reason they need such a construct.
There are several reasons such a design emerges; one of them is when the creation of objects of type C needs to be completed with some initialization that, for whatever reason, cannot be done in the class' constructor.
Another reason for this way of constructing objects of class C is the Singleton design pattern; which in fact is an "anti-pattern", but this is another discussion; in order to implement a Singleton, class C should look like this:
class C
{
private static $instance = NULL;
protected function __construct()
{
}
public static function getObject()
{
if (! isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
Singleton or not, because method getObject() is static it cannot be stubbed or mocked by the test frameworks and its original implementation have to be used. More, because it is the only way to create objects of class C, other classes that use this class cannot be tested in isolation.
All in all, even the construction is possible, it is not recommended. Enforcing the creation of objects of class C using language mechanisms made the class a nuisance for testing other classes that use it.
If the creation of objects of class C needs to be done by a certain method because of its complex initialization, a better way is use the Builder design pattern. Make it a non-static method of another class (the "builder") and instruct the programmers (using the class documentation) to not create objects of class C directly, using new. This way it does not affect the testability of other classes.
I want to disable a class to be instantized by new operator
A common approach is to privatize the constructor.
class Example {
private function __construct() {
}
}
The following would result in a fatal error.
$object = new Example();
While this will work, I would encourage you, and future readers, to review Design Patterns in PHP.
I've got a Validator class and a UserValidator class which extends from it.
My Validator has a public method setRule(...) with public visibility.
When I extend from it I want to change the visibility of the setRule(...) parent method to private/protected within the child so that it's only visible for the child and no outsiders can call this method from the child.
Is that possible? If so, how could I achieve it?
From an architectural point of view this is not recommended. As already stated in the comments the clean way would be to set your method to protected so only children can access it.
I cannot think of a single use case that would put me in the need to call a public method on a parent class but where I am not allowed to call it on the child class.
That's against the Open/Closed principle. Classes should be open for extension, but not for modification.
Since that was not the question I'll provide a way how that can be achieved though. But note:
This method makes use of an extra class which will be responsible for the instantiation
It's a hack. This solution will not make use of PHP's native language features when throwing accessibility errors.
First let's define the classes you already had
<?php
class Validator {
public function setRule()
{
echo "Hello World";
}
}
class UserValidator extends Validator {
public $prop = 'PROPERTY';
}
There's nothing special here. So let's go on and create a custom exception class for the visibility error.
<?php
class MethodNotAccessibleException extends Exception {}
This exception will be thrown when we try to invoke a "pseudo-private" method on the child class.
Now we want to create the Class that will be responsible for instantiating your child class. It is basically just a wrapper that defines a lock property which holds method names that should not be accessible.
<?php
class PrivateInstanceCreator {
protected $reflectionClass;
protected $lock = [];
protected $instance;
public function __construct($classname, $args = [])
{
// We'll store an instance of the reflection class
// and an instance of the real class
$this->reflectionClass = new ReflectionClass($classname);
$this->instance = $this->reflectionClass->newInstanceArgs($args);
return $this;
}
// The lock method is able to make a method on the
// target class "pseudo-private"
public function lock($method)
{
$this->lock[] = $method;
return $this;
}
// Some real magic is going on here
// Remember. This class is a wrapper for the real class
// if a method is invoked we look for the method
// in the real instance and invoke it...
public function __call($method, $args)
{
// ... but as soon as this method is defined as
// locked, we'll raise an exception that the method
// is private
if(in_array($method, $this->lock))
{
$reflectionMethod = $this->reflectionClass->getMethod($method);
if($reflectionMethod->isPublic())
throw new MethodNotAccessibleException('Method: __' . $method . '__ is private and could not be invoked');
}
return call_user_func_array([$this->instance, $method], $args);
}
// The same goes for properties
// But in this case we'll do no protection
public function __get($prop)
{
return $this->instance->{$prop};
}
}
Our final step is the instantiation.
<?php
$userValidator = new PrivateInstanceCreator('UserValidator', []);
$userValidator->lock('setRule');
$userValidator->setRule(); //Will throw an exception
Instead of instantiating the class directly we'll do it by using our custom wrapper class.
Of course you could handle it in the child class itself, but that's a way to accomplish your task without touching the classes directly.
Having said that, it is still a dirty hack whose usage should be avoided if possible. If you would instantiate the child class directly the inherited methods would still be public.
So if a developer has no knowlege about the wrapper class he'll have a hard time to figure out how to instantiate the child class properly.
Update:
To make the child class uninstantiable directly you can set the constructor to private and call newInstanceWithoutConstructor() from the reflection class, which is even dirtier, since that would make Dependency Injection for the class completely impossible. I'm just mentioning it for completenesses sake. Usage is still not recommended
Working with a PHP library class, and I'd like to wrap all of its public functions in a subclass... Something along the lines of:
class BaseClass
{
function do_something()
{
some;
stuff;
}
function do_something_else()
{
other;
stuff;
}
/*
* 20-or-so other functions here!
*/
}
class SubClass extends BaseClass
{
function magicalOverrideEveryone()
{
stuff-to-do-before; // i.e. Display header
call_original_function(); // i.e. Display otherwise-undecorated content
stuff-to-do-after; // i.e. Display footer
}
}
Boiling it down, I'd prefer not to have to override every superclass method with the same wrapper code, if there's a [somewhat elegant / clean] way to do it all in one place.
Is this possible? I suspect I'm in metaprogramming land here, and don't even know if PHP offers such a beast, but figured I'd ask...
You could do this easily with the __call magic method and a generic "proxy" class which doesn't inherit directly from the base class.
Here is a (near) complete implementation of a proxying class which wraps whatever object you pass it. It will invoke some "before" and "after" code around each method call.
class MyProxy {
function __construct($object) {
$this->object = $object;
}
function __call($method, $args) {
// Run before code here
// Invoke original method on our proxied object
call_user_func_array(array($this->object, $method), $args);
// Run after code here
}
}
$base = new BaseClass();
$proxy = new MyProxy($base);
$proxy->doSomething(); // invoke $base->doSomething();
You would of course want to add a bit of error handling, like asking the proxied object if it responds to the given method in __call and raising an error if it doesn't. You could even design the Proxy class to be a base-class for other proxies. The child proxy classes could implement before and after methods.
The downside is that your "child class" no longer implements BaseClass, meaning if you're using type-hinting and want to demand that only objects of type BaseClass are passed into a function, this approach will fail.
If the method names of SubClass may differ slightly from the original method names of BaseClass, you could write a generic wrapper with __call(). If the method names must match, I don't see how you could achieve your goal without manually overwriting each method. Maybe you could use the funcall PECL to do this - but you'd have to be able to load that PECL in the first place.
If you can make the methods of BaseClass protected, the __call() approach in SubClass will work.
If you do not need to extend the class, #meager's approach is perfectly fine. Please note that __call() and call_user_func_array() do impose a certain overhead.
If I understand you right, you want to extend a class, but not allow any of methods from the parent to be called. Instead, you want to call all of the methods yourself in one method in the new class.
So why do you even want to inherit in the first place? It sounds a lot like you should just create an adapter/decorator for your BaseClass.
class SubClass
{
function magicalOverrideEveryone()
{
BaseClass bc = new BaseClass();
bc.do_something();
bc.do_something_else();
}
}
you might be looking for the decorator pattern:
class A
{
function do1(){
}
}
class DecoratorForA extends A
{
private A original;
public DecoratorForA( A original )
{
this.original = original;
}
function do1(){ //<-- override keyword in php?
stuffBefore();
original->do1();
stuffAfter();
}
}
since this is not what you want, maybe this link is of help?
http://code.google.com/p/php-aop/
Here is a simple example:
class Class_A {
protected $_property;
public function method()
{
Class_B::method($this);
}
public function getProperty()
{
return $this->_property;
}
}
class Class_B {
public static function method(Class_A $classA)
{
$classA->getProperty();
}
}
$classA = new ClassA();
$classA->method();
Is it ever okay to pass $this as a parameter to the method of another class? Or is that always going to be tight coupling? I could pose another similar example using a Factory Pattern in place of the static method call.
It depends on the exact behaviour of Class_A and Class_B, but in general it would probably be better to define an interface which is implemented by Class_A and type hint for that. The methods of Class_A that are required by Class_B (e.g. getProperty()) should appear in your interface. Then, if you want to switch Class_A with another class at a later date, all it has to do is implement the same interface.
Yet again, it depends on the behavior of the classes in question, but if there was another Class_C for example that also used Class_B 's static method you might want to consider having Class_A and Class_C extend Class_B. More information can be found on the php object inheritance page.