How to extend only one parent? - php

Let's say I have 2 classes
class BaseClass {
...
}
class SomeClass extends BaseClass {
}
now I want to create third class, that will only extend SomeClass, but not get anything from BaseClass. Is that even possible?
I'm writing Selenium tests with webdriver and want to check data from Selenium against DB or WebServices, but don't want to load the whole framework, just some of our libraries

You can't. That's not how Inheritance works. A class inheriting from SomeClass will always inherit all it's properties and methods, including those of SomeClass inherited from BaseClass. You can limit access to them through Visibility, but only from private over protected to public, not the other way round, e.g. you can loose visibility, but not tighten it.
See the chapters in the PHP Manual about Inheritance and Visibility:
http://php.net/manual/en/language.oop5.inheritance.php
http://php.net/manual/en/language.oop5.visibility.php
Another option would be to use some sort of Facade around an instance of SomeClass to control the access to properties and methods accessible in SomeClass, e.g. assuming your SomeClass has a method foo() and inherits bar() from BaseClass, you could do
class LimitedAccess
{
private $instance;
public function __construct(SomeClass $someClass)
{
$this->instance = $someClass
}
public function foo()
{
return $this->instance->foo;
}
}
and then you can funnel all access through this Facade effectively preventing access to BaseClass::bar(). Note, that this will not change the inheritance hierarchy in any way. It just controls access.

Think about as Human...
You have mother and she has mother...
You cant be son of your mother without being grandson of your grandmother..
same is at PHP
when Class extends other its AWAYS his child...

You can definitely do that if you put a PROTECTED access modifier on the method in BaseClass that you want to be restricted to be called from the Third class..

Related

How to prevent inheritance of static methods? [duplicate]

So let's say I have classes called parent and child, which will be then used from PHP file called caller.php
class Child extends Parent {
}
class Parent {
public function parentMethod(){
}
}
caller.php
PREVENTED:
$child = new Child();
$child->parentMethod();
ALLOWED:
$parent = new Parent();
$parent->parentMethod();
I want to prevent calling parentMethod like this. But if I created Parent object I want to be able to call the parentMethod. Is there some way that I can use to hide this method from being public in Child class, but still allowing parent object to call this method publicly?
Only solution I have come up with so far is making those methods protected and then creating an other class that would extend parent and then have public method for each function that it needs, but that doesn't sound very smart.
Actually, you should ask yourself: why do you need such restriction? You've defined your method as public - thus, you told PHP that it should be visible everywhere. So to prevent child calls you should use private visibility definition.
There is a way to check if call is made from parent class, like:
class ChildClass extends ParentClass {}
class ParentClass
{
public function parentMethod()
{
if(get_class($this) != __CLASS__)
{
throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
}
}
}
But I would not recommend to do that. Reasons are:
Readability. Your method is just ordinary public method. Looking to it it's impossible to say either you should use it with child calls or not. Thus, to maintain such code you'll need to check that restriction in code. Now imagine that you have ~50 methods like that. And dozen of classes like that.
Possibly, breaking Law of Demeter. Why should parent class be aware of it's childs when using such limitation?
Finally, it's just unexpected behavior. Looking to definition, anybody will see that you're extending one class by another. Thus, by definition all inherit methods with proper visibility must be inherited. And your logic changes that.
You may think about composition, not inheritance. That may be right way to implement your logic (however, I can't tell that for sure since I don't know whole background)
You can rearrange your code by adding a base parent class for both of your mentioned classes. Like so:
class Base {
public function inheritableMethod1() {}
public function inheritableMethod2() {}
}
class Child extends Base {
}
class Parent extends Base {
public function additionalMethod() {}
}
Move all inheritable methods from the Parent class to the Base, and leave there only those which must not be called on Child (the parentMethod in your example).
The base class optionally might be abstract to prevent instantiating it directly.
Check if Abstract Class suits your needs:
PHP: Class Abstraction
class Child extends Parent {
public function parentMethod(
# Code
}
}
Abstract class Parent {
abstract public function parentMethod();
}

PHP defining private abstract function/method

Went over a thing like this and I don't know
abstract class Foo {
abstract private function test();
}
Is this a nonsense or NOT?
If not please explain why.
if you speak about private range inside you abstract class, no it is not a nonsence
Since an abstract class can contain functionality (as opposed to an interface) it can have private variables or methods.
I will give you this link with a great answer (even it is in java, it is the same with php) Why is there a private access modifier in an abstract class in Java, even though we cannot create an instance of an abstract class?
Abstract methods cannot be private, because by definition they must be implemented by a derived class. If you don't want it to be public, it needs to be protected, which means that it can be seen by derived classes, but nobody else.
The PHP manual on abstract classes shows you examples of using protected in this way.
http://php.net/manual/en/language.oop5.abstract.php
It makes sense if you want to make that method inaccessible further down in the inheritance chain, e.g. grandchildren of that abstract class. For example:
abstract class Foo {
abstract private function test();
}
class FooChild extends Foo {
private function test()
{
// Here you implement the body of the method
}
public function bar()
{
$this->test(); // This will work
// Do something else
}
}
class FooGrandChild extends FooChild {
}
$grandchild = new FooGrandChild();
$grandchild->test(); // This will throw an exception

Enforcing variable declaration for a subclass in php

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.

How to prevent usage of public parent methods in child instance in PHP?

So let's say I have classes called parent and child, which will be then used from PHP file called caller.php
class Child extends Parent {
}
class Parent {
public function parentMethod(){
}
}
caller.php
PREVENTED:
$child = new Child();
$child->parentMethod();
ALLOWED:
$parent = new Parent();
$parent->parentMethod();
I want to prevent calling parentMethod like this. But if I created Parent object I want to be able to call the parentMethod. Is there some way that I can use to hide this method from being public in Child class, but still allowing parent object to call this method publicly?
Only solution I have come up with so far is making those methods protected and then creating an other class that would extend parent and then have public method for each function that it needs, but that doesn't sound very smart.
Actually, you should ask yourself: why do you need such restriction? You've defined your method as public - thus, you told PHP that it should be visible everywhere. So to prevent child calls you should use private visibility definition.
There is a way to check if call is made from parent class, like:
class ChildClass extends ParentClass {}
class ParentClass
{
public function parentMethod()
{
if(get_class($this) != __CLASS__)
{
throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
}
}
}
But I would not recommend to do that. Reasons are:
Readability. Your method is just ordinary public method. Looking to it it's impossible to say either you should use it with child calls or not. Thus, to maintain such code you'll need to check that restriction in code. Now imagine that you have ~50 methods like that. And dozen of classes like that.
Possibly, breaking Law of Demeter. Why should parent class be aware of it's childs when using such limitation?
Finally, it's just unexpected behavior. Looking to definition, anybody will see that you're extending one class by another. Thus, by definition all inherit methods with proper visibility must be inherited. And your logic changes that.
You may think about composition, not inheritance. That may be right way to implement your logic (however, I can't tell that for sure since I don't know whole background)
You can rearrange your code by adding a base parent class for both of your mentioned classes. Like so:
class Base {
public function inheritableMethod1() {}
public function inheritableMethod2() {}
}
class Child extends Base {
}
class Parent extends Base {
public function additionalMethod() {}
}
Move all inheritable methods from the Parent class to the Base, and leave there only those which must not be called on Child (the parentMethod in your example).
The base class optionally might be abstract to prevent instantiating it directly.
Check if Abstract Class suits your needs:
PHP: Class Abstraction
class Child extends Parent {
public function parentMethod(
# Code
}
}
Abstract class Parent {
abstract public function parentMethod();
}

couple of questions about OO and classes in PHP

I am learning about OO and classes, I have a couple of questions about OO and classes in PHP
As I understand it, a class that extends another class simply means that the class that extends the other class has access to the variables/properties and the functions/methods of the class that it is extending from. Is this correct?
I know that a static method or property are basically the same as a procedural function or variable outside of a class and can be used pretty much anywhere. Is this correct?
Public means any class can access it and Private means only the class that is is encapsulated in or a class that is extended from the owner of can access and use. Is this correct?
1) Yes, that's correct. A child class inherits any protected or public properties and methods of its parent. Anything declared private can not be used.
2) This is true. As long as the class is loaded (this goes well with your autoloading question from before), you can access static methods via the scope resolution operator (::), like this: ClassName::methodName();
3) You have the meaning of public correct, but as I mentioned earlier, private methods can only be used by the class they are declared in.
class parentClass
{
private $x;
public $y;
}
class childClass extends parentClass
{
public function __construct() {
echo $this->x;
}
}
$z = new childClass();
The above code will result in a NOTICE error being triggered, as $x is not accessible by childClass.
Notice: Undefined property:
childClass::$x
If $x was declared protected instead, then childClass would have access. Edit: A property declared as protected is accessible by the class that declares it and by any child classes that extend it, but not to the "outside world" otherwise. It's a nice intermediate between public and private.
For 1. As I understand it, a class that extends another class simply means that the class that extends the other class has access to the variables/properties and the functions/methods of the class that it is extending from. Is this correct?
ANS: That is correct but that is not all. The extending class can also customize the extended class by overriding the method of the extended class. And ofcouse, it can also extend the super class functionality by adding new fields and methods.
For 2. I know that a static method or property are basically the same as a procedural function or variable outside of a class and can be used pretty much anywhere. Is this correct?
ANS: Yes that is correct and as zombat said as long as the class is public and loaded and the property and method is public. In other word, you are using the class as name space of those elements.
For 3. Public means any class can access it and Private means only the class that is is encapsulated in or a class that is extended from the owner of can access and use. Is this correct?
ANS: Think of it as physical properties, public computer (at a library) can be used by everyone and your private computer (supposibly) can only be used by you.
Just to added to Zambat comment.
There's very little need to declare anything private, as a general rule use protected instead.

Categories