I have an abstract class like this
<?php
abstract class AbastractCreationCommand extends AbstactCommand {
protected $repository;
function handle($payload) {
$this->repository->create($payload);
}
}
class TagCreationCmd extends AbstractCreationCommand {
function __constructor() {
$this->repository = new TagRepository();
}
}
?>
Questions:
is there a way I could enforce the definition of the repository class in the subclasseses of the AbstractCreationCommand ?
Do I need to create a test for each subclass and call handle method or is another way to test all my code?
Answering number 1: You cannot enforce the creation of anything in subclasses from within your abstract class. At least not during instantiation. Everything in the subclass is optional.
However, your code in the abstract class could check whether or not the necessary objects have been defined when executing the part of the code that needs it, like this:
abstract class AbastractCreationCommand extends AbstactCommand {
protected $repository;
function handle($payload) {
if (!$this->repository instanceof TagRepository) {
throw new \InvalidArgumentException('Need a TagRepository');
}
$this->repository->create($payload);
}
}
However, is likely doing the complaining too late. And the reason may be because you are using inheritance instead of composition, or are inheriting the wrong things.
First of all, you are not doing dependency injection. Your subclass should not directly instantiate that TagRepository. This leads to problems testing your abstract class' code, as well as the subclass code, because you cannot provide a mock object instead. This severely limits the ability to test your code in isolation.
Also, the subclass cannot work without knowing very specifically how to inherit the abstract class beyond implementing any abstract functions. If both abstract and subclass come from you as the author, I would consider it to be ok to impose doing all things correctly on you. But if you expect other developers to inherit that abstract class (and your question sounds like this might be the background problem), then you shouldn't do this at all.
Abstract classes do provide some common functions to a set of subclasses through inheritance. But the same thing could be achieved if you put all the code into a non-abstract class and inject this class into independent ex-sub classes. They will call these common functions as public methods instead of private or protected, and the testing of the common code is also easier, because the methods are public.
Also note that you already have three levels of inheritance, which is nearing a uncomfortable level: AbstractCommand -> AbstractCreationCommand -> TagCreationCmd.
The problem is that everything you change in AbstractCommand has to be done with two levels of inheriting objects in mind. You cannot simply change a protected variable's name. You cannot simply add a protected (or public) variable without checking if any of the sub classes already has such a variable with the same name - unless you intend to share it.
The problems with maintaining code that is inherited is not with the classes at the end of the inheritance chain, but with these at the top. Just think about how many classes might be affected with different usage contexts: If you have AbstractCreationCommands, you will have AbstractDeletionCommands and AbstractChangeCommands and AbstractDoNothingCommands, and a plethora of concrete commands of all these kinds doing plenty of different stuff. Just imaging that on each level, you have four classes - this makes you having to maintain one base class, four inheriting classes, and four times four concrete classes - for a whopping 21 classes in total, all of them having to be tested, and likely none of them gaining any benefit from being an instanceof AbstractCommand.
Answering number 2: Yes, you have to test all subclasses - these are the ones that get instantiated and used. You should also test the abstract class' code in isolation. PHPUnit offers to instantiate an abstract class with the mock framework, so any abstract method would be mocked and could be configured. However, I always have a bad feeling when I use a mock as the real tested object because I am not really testing the pure code, but some combination of mock code and real code.
A possible way out is to create a test class that barely does anything beyond extending the abstract class, and work with this one.
1.Yes. I do the same when I need to force instantiation of some dependancies. And this way is support GRASP: Creator principle.
Another way to accomplish that with dependency injection, but this way broke Creator principle:
class TagCreationCmd extends AbstractCreationCommand {
function __constructor(TagRepositoryInterface $tagRepository) {
$this->repository = $tagRepository;
}
}
If follow 3 rules of TDD you should write test for each line of code. So the answer is yes.
Is there a way I could enforce the definition of the repository class in the subclasseses of the AbstractCreationCommand ?
I don't see the necessity tbh. If your AbstractCreationCommand needs a repo to work, add it as a constructor param. This doesn't enforce the repo to be injected because a subtype can override the constructor, but it should be abundantly clear that an AbstractCreationCommand subtype requires some sort of repo then, e.g.
abstract class AbstractCreationCommand extends AbstractCommand
{
private $repository;
public function __construct(Repository $repository)
{
$this->repository = $repository
}
protected function getRepository(): Repository
{
return $this->repository;
}
// …
You could also use a Template Method pattern to indicate that any subtype will utilize a repo by adding an abstract getter for the repo. The subtype will have to implement that method then. It's then up to the developer to decide on the implementation:
abstract class AbstractCreationCommand extends AbstractCommand
{
public function handle()
{
$this->getRepository()->create();
}
abstract function getRepository(): Repository;
// …
If you really must enforce it at creation level, you can set the abstract type's constructor to final protected and do any subtype creation in a static factory method, e.g.
abstract class AbstractCreationCommand extends AbstractCommand
{
private $repository;
final protected function __construct(Repository $repository)
{
$this->repository = $repository;
}
// …
This now prevents direct instantiation of any subtypes via new. Trying to new a subtype, will result in PHP Fatal error.
Instead the subtype must be created like this:
class TagCreationCommand extends AbstractCreationCommand
{
private $foo;
public static function create(Repository $repository, Foo $foo)
{
$command = new static ($repository);
$command->setFoo($foo);
return $command;
}
protected function setFoo(Foo $foo)
{
$this->foo = $foo;
}
// …
Then you'd call TagCreationCommand::create(new TagRepository, new Foo); to get a new instance. Since you cannot override the constructor and have to call the parent constructor from within the static create method, you effectively enforce a Repository now to be there. I added the Foo stuff only to illustrate how you'd use additional dependencies.
As you can hopefully see, this requires quite a lot of gymnastics compared to the much more lightweight previous two approaches that will basically result in the same outcome. After all, if there is no repo, the code will fail. And since you are using tests, this will get noticed. So why bother?
Do I need to create a test for each subclass and call handle method or is another way to test all my code?
If you are overriding the handle method, you should test that behavior in a concrete test class for that subtype.
If your subtypes do not override the handle method, you can create an AbstractCreationCommandTest and put a test for the handle method in there. However, if that is the case, I wonder why you need the AbstractCreationCommand to be abstract in the first place because then it sounds like you just need a CreationCommand.
Following Yan Burtovoy's suggestion, I would go even further and actually enforce a DI container
<?php
abstract class AbastractCreationCommand extends AbstactCommand {
protected $repository;
function __constructor(\DI\Container $container) {
$this->repository = $container->get('TagRepository');
}
function handle($payload) {
$this->repository->create($payload);
}
}
You should create tests for everything that is exposed to users of your library (that would be your application).
So, if you have a subclass that relies on handle() being called then you should write a test for that. Reason being that in 6 months someone might change the inheritance or overwrite the handle() method and change the initial expected behaviour.
I'm trying to write an abstract class (or interface) which forces the extending class to implement a protected static function.
But this is neither possible with an abstract class nor an interface.
Errors:
static functions should not be abstract
access type for interface members must be omitted
Any ideas how to accomplish that?
UPDATE
The purpose is basically to call the public function statically. This way the class does not need to be instanciated.
It is also not necessary to make _doSpecificStuff() callable from class-external code.
abstract class Foo
{
public static function doStuff()
{
[generic code]
static::_doSpecificStuff();
}
// sth like that would be nice to have:
abstract static protected function _doSpecificStuff();
}
From a theoretical as well as a practical standpoint, there's no real need to declare a static method abstract.
Abstract methods are there to have a child class fill in a blank. That's typically because the parent class (the original abstract class) does some generic operation, but can/must be adapted to certain specific situations and can thus force child classes to implement only this particular variable part in the otherwise generic algorithm. Abstract methods are supposed to be a blank spot within a larger algorithm.
A parent method would call implementations of its abstract methods without knowing or caring who implements them or how they're implemented:
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
Foo doesn't care who or what fills in the blank doSomethingSpecific, it just relies on it being there and its signature, which abstract enforces. The specific object which implements this method or how it implements it is variable. This is important and is at the core of the issue.
Declaring a static method abstract is pretty useless in this scenario. Any static method can just as well be implemented as a non-static method, so there's no use for it here. If the class itself is supposed to call the abstract method as part of a larger generic algorithm as described above, there's no need for a static method.
So the only scenario left for a static method is for a public static method which is callable from anywhere:
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
The thing is, since the abstract class Foo is not itself calling this function but this function is only called from external code, you're not really talking about a fill-in-the-blank method, you're talking about an interface. So, you should be using an interface instead.
But even there, since you have to type the specific class name in your source code, hardcoded, there's little point for an interface as well.
The point of declaring an interface or abstract method signature is that you want to fix the method signature so any code can call that particular method without caring what object it's calling it on in particular. But since you have to hardcode the class name, there's no variability in the object you're calling it on. If you type Baz::bar(), you know exactly what class you're calling what method on. Therefore there's little point in abstracting the interface/signature.
Compare:
interface FooInterface {
public function bar();
}
function baz(FooInterface $foo) {
$foo->bar();
}
The function baz can rely on its argument having a bar() method due to the interface declaration. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
The class Foo can rely on it having the doSomethingSpecific method. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
What exactly are you relying on or abstracting here? You can be pretty darn sure Baz will have the method bar() every time, because you're only ever calling it on the same hardcoded class. Nothing is variable here.
Ok, so I've read lots of posts on here about this, but I think this is a specific and new question.
I want the functionality of what lots of us on here wrongly call an "abstract static method". That is: I want a class that insists classes that extend it implement certain static methods.
It seems there are two roads round the much discussed problem of not allowing abstract static, but both seem inelegant.
Problem
The following generates an error: "PHP Strict Standards: Static function A::fn() should not be abstract".
<?php
abstract class A
{
abstract static public function fn();
}
class B extends A
{
static public function fn()
{
// does something on class vars etc.
}
}
Solution 1: use Interfaces
<?php
interface iA {
static function fn();
}
abstract class A implements iA
{
} // obviously this would have other stuff in it in reality
class B extends A
{
static public function fn()
{
// does something on class vars etc.
}
}
The problem with this is that an interface assumes (dictates) that all the methods be public. So while this achieves the goal of insisting that sub-classes of an abstract class have certain static methods, it can only be used for public methods; there is still no way to ensure subclasses of A implement a protected static method.
Protected static methods are useful when the method works entirely on static data but ought not to be called from 'outside'.
Solution 2: exceptions
abstract class A
{
static public function fn()
{
throw new Exception(get_called_class() . " must implement fn()");
}
}
class B extends A
{
static public function fn()
{
// does something on class vars etc.
}
}
This works at runtime if fn() when called. But it's not useful to have to deal with coding syntax mistakes at runtime. And while this could be a hack for one method, it's a lot more code for each method.
Is there something so wrong with this design that the language rightly forbids it? Seems odd that there are various ways to insist subclasses provide most types of method, but not static ones.
It's because static methods belong to the class where they are defined. A::fn() and B::fn() are two different methods, regardless of the inheritance tree. So it makes little sense to define A::fn() as abstract.
Maybe your methods in question should not be abstract at all? If you want to use any kind of polymorphism, there should be objects involved.
I might be totally wrong, but I have no problem in using
abstract class A
{
abstract static public function fn();
}
class B extends A
{
static public function fn()
{
print 1;
}
}
B::fn();
It produces 1 as an output. I have run your code in here. What version of php do u use ?
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.
According to the PHP manual, a class like this:
abstract class Example {}
cannot be instantiated. If I need a class without instance, e.g. for a registry pattern:
class Registry {}
// and later:
echo Registry::$someValue;
would it be considered good style to simply declare the class as abstract? If not, what are the advantages of hiding the constructor as protected method compared to an abstract class?
Rationale for asking: As far as I see it, it could a bit of feature abuse, since the manual refers to abstract classes more as like blueprints for later classes with instantiation possibility.
Update: First of all, thanks for all the answers! But many answers sound quite alike: 'You cannot instantiate an abstract class, but for a registry, why not using a singleton pattern?'
Unfortunately, that was more or less exactly a repeat of my question. What is the advantage of using a singleton pattern (a.k.a. hiding __construct()) compared to just declaring it abstract and not having to worry about that? (Like, e.g., it is a strong connotation between developers, that abstract classes are not actually used or so.)
If your class is not meant to define some super-type, it should not be declared as abstract, I'd say.
In your case, I would rather go with a class :
That defines __construct and __clone as private methods
so the class cannot be instanciated from outside
And, this way, your class could create an instance of itself
See the Singleton design pattern, about that, btw
Now, why use a Singleton, and not only static methods ? I suppose that, at least a couple of reasons can be valid :
Using a singleton means using an instance of the class ; makes it easier to transform a non-singleton class to a singleton one : only have to make __construct and __clone private, and add some getInstance method.
Using a singleton also means you have access to everything you can use with a normal instance : $this, properties, ...
Oh, a third one (not sure about that, but might have its importance) : with PHP < 5.3, you have less possibilities with static methods/data :
__callStatic has only been introduced in PHP 5.3
There is no __getStatic, __setStatic, ...
Same for a couple of other Magic methods !
Late Static Binding has only been added with PHP 5.3 ; and not having it often makes it harder, when working with static methods/classes ; especially when using inheritance.
This being said, yes, some code like this :
abstract class MyClass {
protected static $data;
public static function setA($a) {
self::$data['a'] = $a;
}
public static function getA() {
return self::$data['a'];
}
}
MyClass::setA(20);
var_dump(MyClass::getA());
Will work... But it doesn't feel quite natural... and this is a very simple example (see what I said earlier with Late Static Binding, and magic methods).
What you describe is permitted by the PHP language, but it's not the intended usage of an abstract class. I wouldn't use static methods of an abstract class.
Here's the downside of doing that: Another developer could extend your abstract class and then instantiate an object, which is what you want to avoid. Example:
class MyRegistry extends AbstractRegistry { }
$reg = new MyRegistry();
True, you only need to worry about this if you're handing off your abstract class to another developer who won't comply with your intended usage, but that's why you would make the class a singleton too. An uncooperative developer can override a private constructor:
class Registry
{
private function __construct() { }
}
class MyRegistry extends Registry
{
public function __construct() { } // change private to public
}
If you were using this class yourself, you would simply remember not to instantiate the class. Then you wouldn't need either mechanism to prevent it. So since you're designing this to be used by others, you need some way to prevent those people from circumventing your intended usage.
So I offer these two possible alternatives:
Stick with the singleton pattern and make sure the constructor is also final so no one can extend your class and change the constructor to non-private:
class Registry
{
private final function __construct() {
}
}
Make your Registry support both static and object usage:
class Registry
{
protected static $reg = null;
public static function getInstance() {
if (self::$reg === null) {
self::$reg = new Registry();
}
return self::$reg;
}
}
Then you can call Registry::getInstance() statically, or you can call new Registry() if you want an object instance.
Then you can do nifty things like store a new registry instance inside your global registry! :-)
I implemented this as part of Zend Framework, in Zend_Registry
As other guys said, you cannot instantiate an abstract class. You could use static methods in your class to prevent instantiating, but I'm not really a fan of doing so unless I have a proper reason.
I might be little bit off-topic now, but in your example you said you wanted this for Registry pattern class. What is the reason you don't want to instantiate it? Wouldn't it better to create an instance of Registry for each registry you want to use?
Something like:
class Registry {
private $_objects = array( );
public function set( $name, $object ) {
$this->_objects[ $name ] = $object;
}
public function get( $name ) {
return $this->_objects[ $name ];
}
}
I wouldn't even use Singleton in this case.
Setting a class to abstract that only defines static properties/methods won't have a real effect. You can extend the class, instantiate it, and call a method on it and it would change the static class properties. Obviously very confusing.
Abstract is also misleading. Abstract is ment to define an class that implements some functionality, but needs more behaviour (added via inheritance) to function properly. On top of that it's usually a feature that shouldn't be used with static at all. You are practically inviting programmers to use it wrong.
Short answer: A private constructor would be more expressive and fail safe.
There are patterns in OO that are common and well-recognized. Using abstract in an unconventional way may cause confusion (sorry, my some examples are in Java instead of PHP):
abstract class - a class meant to conceptualize a common ancestor, but of which actual instances are not meant to exist (e.g. shape is an abstract superclass for rectangle and triangle).
Commonly implemented by:
use abstract modifier on class to prevent direct instantiation, but allow deriving from the class
utility class - a class that does not represent an object in the solution space, but rather is a collection of useful static operations/methods, e.g. Math class in Java.
Commonly implemented by:
make class non-derivable, e.g. Java uses the final modifier on class, and
prevent direct instantiation - provide no constructors and hide or disable any implicit or default constructors (and copy constructors)
singleton class - a class that does represent an object in the solution space, but whose instantiation is controlled or limited, often to insure there is only one instance.
Commonly implemented by:
make class non-derivable, e.g. Java uses the final modifier on class, and
prevent direct instantiation - provide no constructors and hide or disable any implicit or default constructors (and copy constructors), and
provide a specific means to acquire an instance - a static method (often getInstance()) that returns the only instance or one of the limited number of instances
abstract really is meant to indicate a "blueprint", as you call it, for class inheritance.
Registries generally follow a singleton pattern, which means they it would instantiate itself in a private variable. Defining it as abstract would prevent this from working.
I wouldnt use an abstract class. Id use something more akin to a singleton with a protected/private constructor as you suggest. There should be very few static properties other than $instance which is the actual registry instance. Recently ive become a fan of Zend Frameworks typical pattern which is something like this:
class MyRegistry {
protected static $instance = null;
public function __construct($options = null)
{
}
public static function setInstance(MyRegistry $instance)
{
self::$instance = $instance;
}
public static function getInstance()
{
if(null === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
}
This way you get a singleton essentially but you can inject a configured instance to use. This is handy for testing purposes and inheritance.
The purpose of an abstract class is to define methods that are 1) meaningful to other classes and 2) not meaningful when not in the context of one of those classes.
To paraphase some of the php docs, imagine you are connecting to a database. Connecting to a database doesn't make much sense unless you have a particular kind of database to connect to. Yet connecting is something you will want to do regardless of the kind of database. Therefore, connecting can be defined in an abstract database class and inherited, and made meaningful by, say, a MYSQL class.
From your requirements, it sounds like you don't intend to do this but instead simply require a class without an instance. Whilst you could use an abstract class to enforce this behaviour, this seems hacky to me because it abuses the purpose of abstract classes. If I encounter an abstract class, I should be able to reasonably expect that this will have some abstract methods, for example, but your class will have none.
Therefore, a singleton seems like a better option.
However, if the reason you wish to have a class without an instance is simply so that you can call it anywhere then why do you even have a class at all? Why not just load every variable as a global and then you can just call it directly rather than through the class?
I think the best way to do this is to instantiate the class and then pass it around with dependency injection. If you are too lazy to do that (and fair enough if you are! Its your code, not mine.) then don't bother with the class at all.
UPDATE: It seems like you are conflicted between 2 needs: The need to do things quickly and the need to do things the right way. If you don't care about carrying a ton of global variables for the sake of saving yourself time, you will assumedly prefer using abstract over a singleton because it involves less typing. Pick which need is more important to you and stick with it.
The right way here is definitely not to use a Singleton or an abstract class and instead use dependency injection. The fast way is to have a ton of globals or an abstract class.
From my understanding, a class without instance is something you shouldn't be using in an OOP program, because the whole (and sole) purpose of classes is to serve as blueprints for new objects. The only difference between Registry::$someValue and $GLOBALS['Registry_someValue'] is that the former looks 'fancier', but neither way is really object-oriented.
So, to answer your question, you don't want a "singleton class", you want a singleton object, optionally equipped with a factory method:
class Registry
{
static $obj = null;
protected function __construct() {
...
}
static function object() {
return self::$obj ? self::$obj : self::$obj = new self;
}
}
...
Registry::object()->someValue;
Clearly abstract won't work here.
I would say it's a matter of coding habbits. When you think of an abstract class it is usually something you need to subclass in order to use. So declaring your class abstract is counter-intuitive.
Other than that is it just a matter of using self::$somevar in your methods if you make it abstract, rather than $this->somevar if you implement it as a singleton.