I have an abstract class with an abstract method 'run'. Child classes extending this implements run and returns a bool as output.
Is there a way that I can get the status of run (true/false) method in the abstract class.
I want this as I am trying to add few statistics as how many classes failed/passed to execute the run method. I already have many classes extending this and don't want to add anything into those and get these statistics for free.
abstract class parent {
// I need the status of the run method in here
public abstract function run();
}
class child extends parent {
public function run() {
if (implementation) {
return true;
} else {
return false;
}
}
}
Help appreciated.
Define a non-abstract method in the parent that calls the abstract method and gets the result.
abstract class parent {
private $run_result;
public function run() {
$this->run_result = $this->run_internal();
}
abstract protected function run_internal();
}
class child extends parent {
protected function run_internal() {
if (implementation) {
return true;
} else {
return false;
}
}
}
Related
here is the class structure. I want Observer:callme() to be callable from Children too.
class Observer
{
protected callme()
{
}
}
class Parent extends Observer
{
function createChild()
{
$this->callme(); // this is OK
return new Child ($this);
}
}
class Child
{
private $this myParent;
public function __constructor ($myParent)
{
$this->myParent = $myParent;
}
public function __destroy()
{
$this->myParent->callme(); // FAIL!
}
}
so how to make FAIL work? (without making it public, because its only for used inside "Parent" and its "Children")
The problem is that a protected method is only accessed from the same class or the class children. What you can do is extend your Child class from Parent, like this:
class Child extends Parent
{
public function __constructor ()
{
parent::__constructor();
}
public function __destroy()
{
$this->callme(); // Should work!
}
}
Or just change the method to public.
And, btw, is this code some kind of real code that you will use? That constructor receiving the parent object seems to be so wrong. What are you trying to accomplish?
protected means that you can call that method only from the same class and from subclasses. What you want to do is not possible. The protected keyword would be pointless if you could call these methods from everywhere.
In C++ there is the friend keyword to achieve what you want: you could define Child as friend of Observer (this has to be done from within Observer), and then you can call all methods in Observer (including private and protected) from within methods of Child. But such a keyword does not exist for PHP.
My comment on your question explains why it doesn't work. This answer shows a way to accomplish what you asked based upon your clarification that MyChild should not extend MyParent.
This is a hack example that makes it work by exploiting the fact that php doesn't care if you call protected methods on other instances than yourself as long as you share the ancestor of the protected method.
I had to change the code some to make it valid php. __constructor is not the name of a php constructor.
hacky.php
<?php
class Observer
{
protected function callme()
{
echo 'I was called from ' . get_called_class(), PHP_EOL;
}
}
class MyParent extends Observer
{
public function createMyChild()
{
$this->callme(); // this is OK
return new MyChild ($this);
}
}
class MyChild extends Observer // hackey extends
{
private $myMyParent;
public function __construct($myMyParent)
{
$this->myMyParent = $myMyParent;
$this->myMyParent->callme();
}
}
$p = new MyParent;
$c = $p->createMyChild();
Result:
$ php hacky.php
I was called from MyParent
I was called from MyParent
I think I found the solution:
class Parent extends Observer
{
function createChild()
{
$this->callme(); // this is OK
return new Child (function() { $this->callme(); });
}
}
class Child
{
private $gatewayFunction;
public function __constructor (Closure $gatewayFunction)
{
$this->gatewayFunction = $gatewayFunction;
}
public function __destroy()
{
$this->gatewayFunction->__invoke();
}
}
Who is going to crap himself? :)
I'm trying to access and modify data that is in a parent class which is a child of another class.
I've a parent class
class GrandParent {
protected $data = 1;
public function __construct() {}
public function getData() {
return $this->data;
}
}
Below is my first level child
class Child extends GrandParent {
protected $c1Data;
public function __construct() {
$this->c1Data = parent::getData();
$this->c1Data = 2;
}
public function getData() {
return $this->c1Data;
}
}
If I try to instantiate the Child class and do getData(), I get 2 which is normal. I've another class that inherits Child.
class GrandChild extends Child {
protected $c2Data;
public function __construct() {
$this->c2Data = parent::getData();
}
public function getData() {
return $this->c2Data;
}
}
The problem is that if I try to instantiate GrandChild I and get the data I'm getting null. Is it possible to make my GrandChild class inherit $c1Data = 2 and work with it. I want also to be able to use the Child and GrandParent classes on their own and not be abstract.
You're getting NULL because __constructor of a Child class is not invoked and that's why c1Data property is NOT SET. You should explicitly call for Child __constructor:
class GrandChild extends Child {
protected $c2Data;
public function __construct() {
// here
parent::__construct();
$this->c2Data = parent::getData();
}
public function getData() {
return $this->c2Data;
}
}
This is how you add two integers and display the result with Multi
Level Inheritance in PHP.
<?php
/*
Inheritance:
multiple classes
Parent class/child class
senior and junior
child class extends some data or functions of parent class
child class has its own functions
child class can access all public and protected data and functions
*/
//Multi Level Inheritance Every class extends other class
//Parent Class
class A{
//data
var $a;
function setA()
{
$this->a=10;
}
}
//child class
class B extends A{
var $b;
function setB()
{
$this->b=20;
}
}
class Addition extends B{
function add()
{
$this->setA();
$this->setB();
return $this->a+$this->b;
}
}
class Print1 extends Addition{
function print()
{
$this->add();
print("a=".$this->a);
print("<br/>b=".$this->b);
print("<br/>Addtion:".$this->add());
}
}
//make object
$obj1=new Print1();
$obj1->print();
/*
Make Subtraction, multiplication and division classes and print the values as
a=10
b=20
Addtion=30
Subtraction=-10
Multiplication=200
Division:0.5
*/
?>
I have an abstract class that declares the methods required to its children. It also has a construstor that its children inherits. How can I make the abstract class affect the children of the classes that extends it. To further clarify my question, here is my case:
The Abstract Class (abstract.php):
<?php
include_once 'database.php';
include_once 'validation.php';
abstract class DataOperations extends DatabaseConnection {
//The error string shared by all children of DataOperations
//This will be the message to be displayed in case validation failure
public $validator;
public $err_valid_string;
/**
* The DataOperations' constructor ensures that all of its children can perform database operation
* by automatically starting it for them. In case a child overrides this constructor, this child
* must explicitly start the connection to prevent fatal errors. Also, $validator must be re-instantiated
*/
public function __construct() {
$this->startDBConnection();
$this->validator = new InputValidator();
}
public function __destruct() {
}
abstract public function validateData();
abstract public function loadRecord($key, $cascade);
abstract public function saveRecord();
abstract public function updateRecord();
abstract public function deleteRecord();
}
?>
Now, here is the child object that extends the DataOperations abstract class
class Guest extends DataOperations {
//some properties here
public function validateData() {
//implementation
}
public function newRecord(implementation) {
//implementation
}
public function loadRecord($key, $cascade){
//implementation
}
public function saveRecord() {
//implementation
}
public function updateRecord() {
//implementation
}
public function deleteRecord() {
//implementation
}
}
?>
And here is another class, which is a child of Guest
class Booking extends Guest {
//some properties here
public function validateData() {
//implementation
}
public function newRecord(implementation) {
//implementation
}
public function loadRecord($key, $cascade){
//implementation
}
public function saveRecord() {
//implementation
}
public function updateRecord() {
//implementation
}
public function deleteRecord() {
//implementation
}
}
?>
The problem is, if I remove a method in Booking, say deleteRecord(), PHP won't throw an error because I think abstract class doesn't affect its 'grandchildren'. How can I fix this? I thought of using interfaces but my system already has 11 classes that depends to some methods of the abstract class. It will require intensive refactoring.
As you himself stated interface is best suited solution. Like
include_once 'database.php';
include_once 'validation.php';
interface DbInterface {
abstract public function validateData();
abstract public function loadRecord($key, $cascade);
abstract public function saveRecord();
abstract public function updateRecord();
abstract public function deleteRecord();
}
class DataOperations extends DatabaseConnection {
//The error string shared by all children of DataOperations
//This will be the message to be displayed in case validation failure
public $validator;
public $err_valid_string;
/**
* The DataOperations' constructor ensures that all of its children can perform database operation
* by automatically starting it for them. In case a child overrides this constructor, this child
* must explicitly start the connection to prevent fatal errors. Also, $validator must be re-instantiated
*/
public function __construct() {
$this->startDBConnection();
$this->validator = new InputValidator();
}
public function __destruct() {
}
}
class Guest extends DataOperations implements DbInterface {
- - -
}
class Booking extends Guest implements DbInterface {
- - -
}
First as you see I removed abstract from parent class as I assuming only those methods are abstract. Second as per your problem of 11 classes depend on Abstract class, I would say As you only remove abstract methods, Class implementing abstract methods now should implement interface. It is one time needed task. While classes using other normal methods of abstract class work like previous.
The best and cleanest way would be to have your "BOOKING" class extend the "DATAOPERATIONS" class, instead of GUEST, because looks like you don't have any extra methods in the BOOKING class. other wise make and interface and implement it. That is not the preferred way but you would have to give more info your situation.
To be clear, re-declaring a method in a child class will overwrite the parent class's implementation of that method when called from the child class, while not affecting any additional functionality provided by extending the parent class:
class a
{
function hello()
{
echo "Hello";
}
function goodbye()
{
echo "Goodbye";
}
}
/**
* class b overwrites class a's implementation of method goodbye but will retain
* it's definition for method hello
*/
class b extends a
{
function goodbye()
{
echo "See ya!";
}
}
$object = new b();
$object->hello(); // Hello
$object->goodbye();// See ya!
It appears that you want to implement a consistent interface across multiple class definitions. If this is the case, you will likely want to explore using PHP's interfaces.
These allow you to specify the methods that must exist in your class definition along with their set of arguments (collectively known as the signature). Your class definitions will implement an interface and if your definition does not meet the interface implementation specification, a fatal error will be thrown.
From the PHP manual:
// Declare the interface 'iTemplate'
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// Implement the interface
// This will work
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
You can find more information about interface in the PHP manual:
http://us2.php.net/interface
Finally, it looks like you are hoping to define a common constructor for the child classes. Your child classes can both extend the DataOperations class while implementing a separate interface:
class Guest extends DataOperations implements DatabaseWriter
...
I want to do some cache in my ORM
class Base {
static public $v=array();
static public function createById($id){
if(!array_key_exists($id, static::$v)){
static::$v[$id] = new static; //Get from DB here. new static is just example
}
return static::$v[$id];
}
}
class User extends Base{
}
class Entity extends Base{
}
But now cache is merged
var_dump(User::createById(1));
var_dump(Entity::createById(1));
results
object(Model\User)#4 (0) {
}
object(model\User)#4 (0) {
}
If I made
class Entity extends Base{
static public $v=array();
}
class User extends Base{
static public $v=array();
}
I get what I need:
object(Model\User)#4 (0) {
}
object(model\Entity)#5 (0) {
}
Is it possible to do it without declaration in every class?
If its that important that you don't re-declare the property in each child class, the only solution I can think of is, which isn't exactly what you wanted, but it should get you the same functionality, is sharing the same property on the base class to store the cache for all the child classes, but using the child class name as a key in the cache array:
class Base {
public static $v=array();
public static function createById($id){
$called = get_called_class();
if (!isset(self::$v[$called])) {
self::$v[$called] = array();
}
$class_cache = &self::$v[$called];
if(!array_key_exists($id, $class_cache)){
$class_cache[$id] = new static;
}
return $class_cache[$id];
}
}
Yes, its not pretty... but AFAIK, what you asked for isn't possible.
As the title states, I'm trying to make a method in a parent class required. Although, I suppose it could be any class. For instance:
class Parent
{
function foo ()
{
// do stuff
}
}
class Child extends Parent
{
function bar ()
{
// do stuff after foo() has ran
}
}
Basically, I want foo() to be required to run or Child class doesn't run and returns an error or redirects to a different page. I could call the function, but I'm wondering If I can make it a requirement when extending the parent class.
If you leverage abstract classes and methods, you can force subclasses to implement the missing methods.
abstract class ParentClass
{
public function foo ()
{
// do stuff
$this->bar();
}
abstract protected function bar();
}
class Child extends ParentClass
{
protected function bar()
{
// does stuff
}
}
Subclasses that don't implement bar() will generate a fatal error.
What you should probably do is override Parent::foo() and then call the parent method in the overridden method like so:
class Parent
{
function foo ()
{
// do stuff
}
}
class Child extends Parent
{
function foo ()
{
if(!parent::foo()) {
throw new Exception('Foo failed');
}
// do child class stuff
}
}
Why not just set a boolean in function foo() that acts as a flag. Check to see if it has been set in the child class/functions, and you're all set.
Have the child call the function from the parent in the construct.
class Child extends Parent
{
function bar ()
{
// do stuff after foo() has ran
}
function __construct(){
parent::foo();
}
}
As already mentioned, it sounds like you want foo() to be abstract, forcing child classes to override it.
Any class containing an abstract class in PHP requires your parent class to be abstract too. This means it can't be instantiated (constructed), only derived / sub-classed. If you try to instantiate an abstract class the compiler will issue a fatal error.
http://php.net/manual/en/language.oop5.abstract.php
See the code in Peter Bailey's answer.
If you're not actually initializing any code within parent class you should use an object interface. Interface methods have to be implemented or the script will throw a fetal error.
More information on them can be found: http://us3.php.net/interface.
I think this might be the only way of implementing such functionality, as I don't think there is a built in solution.
class Parent
{
public $foo_accessed = FALSE;
function foo ()
{
$this->foo_accessed=TRUE;
// do stuff
}
}
class Child extends Parent
{
function bar ()
{
if($this->foo_accessed==TRUE) {
// do stuff after foo() has ran
} else {
// throw an error
}
}
}
Do not depend on other methods. Make sure they've ran.
class Parent
{
function foo()
{
// do stuff
}
}
class Child extends Parent
{
private function bar()
{
// do child class stuff
}
public function doFooBar()
{
parent::foo();
$this->bar();
}
}
Following approach will only ever complain after all processing has been done - however if that is fair to you it will definately make sure foo() has been called in the parent class or otherwise trigger a condition that you can act upon.
class DemandingParent {
private $hasFooBeenCalled = false;
public function foo() {
$this->hasFooBeenCalled = true;
/* do Stuff */
}
public function __destruct() {
if (!$this->hasFooBeenCalled) {
throw new Exception("Naughty Child! Call your parent's foo b4 you speak up!");
}
}
}