In my PHP code I have a protected method in an abstract class which we'll call class A. If I create a new class called B which extends A, do I have to simply declare it public in B or do I have to re-write all the implementation so when I instanciate B I can then call this method?
abstract class A {
protected function test() {
//do some stuff here
}
}
class B extends A {
public function test() {
//Do I need to do something here?
}
}
Thank you
Crouz
You need to do parent::test() call - or not do not declare method in child class at all. In second case method will be inherited from parent class while in first case it will be method of B which calls parent method, i.e. method of A.
Also, if you will not declare method in child class, it will not be public, so it may be not the thing you're looking for (mentioned to show how inheritance works). I.e. if you want to have public method - the only way would be calling parent::test() from inside test() method of B class
Related
I am trying to understand one PHP OOP concept, lets say i have two classes A and B. B extends A there fore A is Base/Parent class. If class A has a __construct class B will automatically inherit it...?
Example:
class Car
{
public $model;
public $price;
public function __construct()
{
$this->model = 'BMW';
$this->price = '29,00,00';
}
}
class Engine extends Car
{
parent::__construct();
}
By parent::__construct(); class Engine will execute Car __construct(); automatically?
But I always though if I inherit from parent class the __construct will be executed automatically anyway why would I add this parent::__construct()?
When one class extends another, it inherits all its methods. Yes, that includes the constructor. You can simply do class Engine extends Car {}, and Engine will have a constructor and all other properties and methods defined in Car (unless they're private, which we'll ignore here).
If you define a method of the same name as already exists in Car in Engine, you're overriding that method implementation. That's exactly what it sounds like: instead of Car's implementation, Engine's method is called.
why would I add this parent::__construct()?
If you're overriding a method, yet you also want to call the parent's implementation. E.g.:
class Engine extends Car {
public function __construct() {
parent::__construct();
echo 'Something extra';
}
}
Overriding a constructor in a child class is exactly that, overriding... you're setting a new constructor for the child to replace the parent constructor because you want it to do something different, and generally you won't want it to call the parent constructor as well..... that's why you need to explicitly call the parent constructor from the child constructor if you want them both to be executed.
If you don't create a child constructor, then you're not overriding the parent constructor, so the parent constructor will then be executed
I have 3 PHP classes: abstract DBObject, Organization extends DBObject, University extends DBObject.
Loading the objects ends up with an array of data from the DB.
Each of the constructors knows how to build itself from that array, so I tried this:
abstract class DBObject {
...
public static function load($id) {
return new self(self::loader($id));
}
}
self::loader($id) properly gets the array. I can make the function load() abstract and copy and paste this code into each child, but I was hoping there was a way to do the above. The current error is:
PHP Fatal error: Cannot instantiate abstract class DBObject in /var/www/htdocs/classes/DBObject.php on line 16
What you're looking for is called late static binding. Instead of self you want to refer to the class your method is being called from, so switch to the static keyword:
abstract class DBObject {
...
public static function load($id) {
return new static(static::loader($id));
}
}
Now when called from any sub-class of DBObject the loader function on the sub-class will be called.
I'm a beginner in CodeIgniter and OOP. I was reading a page of CI tutorial here. I found something that made a question in my mind.
Look at this code:
<?php
class News extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('news_model');
}
I think if we made a class that extends CI_Controller, we assume it must have all methods and properties in its parent class (Although we can override them). So, why there is parent::__construct(); in the code?
__construct() is the constructor method of a class. It runs if you declare a new object instance from it. However, if a class implemented its own __construct(), PHP would only run the constructor of itself, not of its parent. For example:
<?php
class A {
public function __construct() {
echo "run A's constructor\n";
}
}
class B extends A {
public function __construct() {
echo "run B's constructor\n";
}
}
// only B's constructor is invoked
// show "run B's constructor\n" only
$obj = new B();
?>
In this case, if you need to run class A's constructor when $obj is declared, you'll need to use parent::__construct():
<?php
class A {
public function __construct() {
echo "run A's constructor\n";
}
}
class B extends A {
public function __construct() {
parent::__construct();
echo "run B's constructor\n";
}
}
// both constructors of A and B are invoked
// 1. show "run A's constructor\n"
// 2. show "run B's constructor\n"
$obj = new B();
?>
In CodeIgniter's case, that line runs the constructor in CI_Controller. That constructor method should have helped your controller codes in some way. And you'd just want it to do everythings for you.
To answer your question directly from the Code Iginiter documentation:
The reason this line is necessary is because your local constructor will be overriding the one in the parent controller class so we need to manually call it.
http://ellislab.com/codeigniter/user-guide/general/controllers.html#constructors
Extension used for all classes.
__construct() used for that class that you use.
Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.
I believe the need of calling the parent constructor/method is a code smell, known as Call super. Besides the error-sensitivity (forgetting this call, you can get unexpected results), it's procedural instead of OOP. After all, the order of statements can lead to unexpected results too.
Read more here: https://martinfowler.com/bliki/CallSuper.html
Inheritance is being used via the keyword extends. The parent class could be setting some values when its constructor is being called. If the parent constructor is not called the values are not set and the child class will not get those values.
Example:
class Super {
protected $a;
public function __construct(){
$this->a = 'Foo';
}
}
class Child extends Super{
protected $b = 'Bar';
public function __construct() {
parent::__construct();
echo $this->a;
}
}
$x = new Child();
Here, the class Child would echo out nothing if the parent constructor was not called.
So in Codeigniter the parent class is probably setting some values that are of help to its children when you call its constructor and those values are only available to its children if the parent constructor is called.
A simple question, does the following make sense ?
Class B extends Class A
class A constructor:
function __construct(){
//do something
}
Class B constructor:
function __construct(){
parent::__construct();
}
Is there any significant advantage to implementing the child constructor at all in this case?
I can only think of :
The entire code for class B will be more "complete" in structure
Would be interesting to know if there is any significant advantages in coding or in structuring etc.
The only time you want to invoke your parent constructor from your subclass (child class) is when you want to add custom code in your constructor.
In your example you can leave out the __construct() method altogether in Class B.
However you might want to do something like this:
class A {
function __construct() {
run_a_function();
$this->set = "a variable";
}
}
class B {
function __construct() {
run_a_function_specific_to_class_b();
$this->set = "a variable specific to class b";
// now call the parent constructor
parent::__construct();
}
}
No. If all your constructor (or any method for that matter) does is call the parent method of the same name, then there's no advantage whatsoever. Just more lines of code.
A local constructor overrides its parent:
<?php
class Blog extends CI_Controller {
public function __construct()
{
parent::__construct();
// Your own constructor code
}
}
?>
If you have a __construct() method in the child class you must call the parent constructor explicitly.
If you have no desire to run anything in the child constructor, do not specify the constructor method in the child and the parents constructor will be called automatically.
If I have the following class:
class foo {
function __construct() {
// Some code
}
}
And then use inheritance to create:
class bar extends foo {
// Some code
}
When I instantiate class 'bar', will it automatically execute the __construct method from 'foo' or do I need to do something else to get that method to execute?
From the manual:
Note: Parent constructors are not
called implicitly if the child class
defines a constructor.
While the documentation doesn't state it explicitly, the inverse of this sentence is also true, i.e., parent constructors are called implicitly if the child class does not define a constructor. Therefore, in your example, instantiating bar would call foo::__construct automatically.
it works, the constructer from the parent class will be inherited.
if you define a new constructor in the instaciated class, it will override the constructor function of the parent class. if you still want to execute the parent constructer you should include
parent::__construct();
in the constructer of thje isntanciated class
The __construct will carry over, yes.
The issue comes when you want to add something to that function, which is when the parent class comes in handy.
class bar extends foo {
$this->doSomethingElse();
parent::__construct();
}
Of course when you extend a class, the subclass inherits all of the public and protected methods from the parent class.