I learned that I can use a parent's constructor in PHP with ParentClass::__construct();.
I imagine it's not possible, but I want to be sure; can I override or remove an aspect of the copied constructor? In other words, if the parent's constructor was
public function __construct(){
print "This is from the parent class";
test();
}
public function test(){
print "Remove this function when copying to child class";
}
is there any way that I can
public function __construct(){
ParentClass::__construct();
//override/remove/negate test() function in the copied construct.
}
Right now, your object structure is like this:
class ParentClass {
public function test(): void {}
}
class ChildClass extends ParentClass {
// This class has access to test() through inheritance
}
What you could have instead:
class BaseClass {
// Here, have everything that's actually common between all subclasses
}
class ClassA extends BaseClass {
public function test(): void {}
}
class ClassB extends BaseClass {
// This class does not have access to test()
}
You could also mix in some interfaces, but that's the basic idea.
Related
I have a base class and I want to have one of its methods called after the extending class is constructed. Ideally this should happen without changing the extended class constructor:
class BaseClass {
protected function doSomethingAfterConstruct() {}
}
class ExtendedClass extends BaseClass {
public function __construct() {
// some custom constructor code
}
}
I could just call $this->doSomethingAfterConstruct() at the end of the ExtendedClass constructor or by calling parent::__construct, but I am looking for a solution where I can implement this behavior by only changing the baseclass.
If it would be not __constructor, but ordinary method, then you can use __call magic method to proxy calls to child class:
All child methods should be non-public visibility, to trigger magic method
class BaseClass {
public function __call($name, $arguments) {
$return = $this->{$name}(...$arguments);
$this->doSomethingAfterMethod();
return $return;
}
protected function doSomethingAfterMethod() {}
}
class ExtendedClass extends BaseClass {
private function randomMethod() {
// some custom method code
}
}
I've already read Why does PHP 5.2+ disallow abstract static class methods? and How to force an implementation of a protected static function - the second is very similar to my case - but I am still without answer. Basically, I want to assure, that every child of my abstract class has implementation of protected static method, without implementing it as this has no meaning and because of lack of key informations there. Also, it must be static (because caller method is static and it has no context) and protected (so I cannot use interface, and I do not want anyone to call it directly), and it will be called by late static binding. Any ideas?
Dummy code below to illuminate my case:
abstract class BaseClass {
public static function foo() {
// some common stuff
static::bar();
// rest of common stuff
}
public function whoooaaa($condition) {
if ($condition) {
AClass::foo();
} else {
BClass::foo();
}
}
}
class AClass extends BaseClass {
protected static function bar() {
// do something
}
}
class BClass extends BaseClass {
protected static function bar() {
// do something else
}
}
// end somewhere else in my code, two constructions, both used:
AClass::foo();
// ....
$baseClassInheritedInstance->whoooaaa($variableCondition);
My only solution, ugly one, is to implement dummy protected static method in base class and throw a generic exception, so that it must be implemented by inheritance.
You can add a static factory that will fill context for casual objects.
class Factory() {
public static getObject($condition) {
$object = $condition ? new A() : new B();
// you can fill context here and/or use singleton/cache
return $object;
}
}
abstract class Base {
abstract function concreteMethod();
}
class A extends Base {...}
class B extends Base {...}
Why does the code below:
class A {
public function foo() {}
}
class B extends A {
private function foo() {}
}
generates an fatal error while this:
class A {
private function foo() {}
}
class B extends A {
public function foo() {}
}
doesn't although the documentation says "If the child doesn't see the parent's private methods, the child can't override them"?
So let's analyze what you have:
class A {
private function foo() {}
}
class B extends A {
public function foo() {}
}
Here class A has a private method, and since it's private it's not seen in class B. So in class B you can create method with the same name. It's not overriding, it's just creating method with the same name.
And in this example:
class A {
public function foo() {}
}
class B extends A {
private function foo() {}
}
Method A::foo is public and you can override it in class B. But as it's public, visibility of children method shouldn't be stricter then parent one. So you can't have B::foo as private, only public.
It is all about semantic. In first example in method foo of class B you can call parent method foo of class A using parent::foo(), but he is a private.
Assume I have this interface...
interface Foo {
public function bar();
public function nothing();
}
I'm tasked with writing an "abstract class that also abstracts the methods", and I just want to make sure that I'm writing this correctly. My code is as follows...
abstract class Bar implements Foo {
abstract public function bar();
abstract public function nothing();
}
Is this the correct way of doing this?
You don't need to implement the interface in your abstract class. Your abstract class provides an interface like contract to classes that extend it.
abstract class Bar {
abstract public function bar();
abstract public function nothing();
public function concreteMethod() {
print "I can do this in an abstract class";
}
}
class Concrete extends Bar {
public function bar() {
print "in bar";
}
public function nothing() {
//nothing
}
}
If you do not have any need to implement some shared (by all subclasses) functionality in the abstract class, you should better derive directly from the interface, to make things not unnecessarily complicated.
In this case, the whole thing could be sensefully simplyfied to:
<?php
interface Foo
{
public function bar();
public function nothing();
}
class C implements Foo
{
public function bar() {
echo 'bar';
}
public function nothing() {
echo 'nothing';
}
}
$obj = new C();
$obj->bar();
?>
Read more at:
Is it good or bad for an abstract class to implement an interface?
I don't know, but one chance is that create abstract class with implements interface like this.
interface Foo {
public function bar();
public function nothing();
}
abstract class Bar implements Foo {
public function bazz() {
echo ' Bye';
}
}
class Test extends Bar {
public function bar()
{
echo 'Hello ';
}
public function nothing()
{
echo 'World';
}
}
By this you have your abstract class having abstract methods from a interface. It also used in some architecture design where you want a parent class as abstract class but define all abstract methods in interface.
So you can't make an abstract static function in php.
The alternatives as I see them are to:
Make the function non-static and write extra boilerplate code to create and store the object so I can access that function.
abstract class Foo {
abstract public function bar();
}
abstract class Good {
public function bar() {
...
}
}
// boilerplate to access Good->bar()... potentially a lot in multiple files
$g = new Good();
$g->bar();
Fill in the static function in my abstract class with a BadMethodCallException, so that any call to a child class which doesn't implement it will throw the exception.
abstract class Foo {
public static function bar() {
throw new BadMethodCallException("Not Implemented By Child Class :(");
}
}
class Good extends Foo {
public static function bar() {
// ...
}
}
class Bad extends Foo {
// no bar implementation
}
Good::bar(); // works
Bad::bar(): // exception
I'm leaning towards 2. but was wondering if there's any community consensus on this issue or best practices.
I ended up making an interface with a static function, then implementing the interface in the abstract class. This forces the child classes to define the method, which is basically what I wanted with an abstract static function.
interface ModelFactoryInterface {
public static function offer();
}
abstract class ModelHelper implements ModelFactoryInterface {
protected $tester;
public function __construct($tester) {
$this->tester = $tester;
}
}
/* Location
* ------------------------------------------------------ */
final class LocationHelper extends ModelHelper {
public static function offer() {
return new Location(...)
}
}