classes interaction methods php - php

Lets say we have class B which extends class A. When creating new instance of class B and providing value into it that value is used in constructor of class A. Please check sample below.
I'm little bit confused about such behavior. If method "display" do not pass value into class A it should not get there, or am i missing something?
class A {
protected $changeableString = 'initial value';
public function __construct($providedText)
{
$this->changeableString = $providedText;
}
public function printString(){
echo $this->changeableString;
}
}
class B extends A {
public function display(){
echo $this->changeableString;
}
}
$test = new B('provided value');
$test->display();
edit: I have changed function __construct from protected to public according comments. It is indeed gives error, so if someone will review this issue now code is correct.

First of all the topic you are talking about is called Inheritance in Object-Oriented Programming (OOP).
If class B has no construct (__construct) then PHP will call the construct of class A.
And about display function, think of it as an addition to everything in class A but will not be available in class A
So class B is like class A but has one more function called display.
Note:
As #Brian said, if you try to call new B('provided value') that will produce the following error:
Fatal error: Uncaught Error: Call to protected A::__construct() from global scope in ..
and to solve it just make the construct of class A public so class B.

Related

Unexpected inheritance behavior of php code

I've written this code for check behavior of my app and i don't why this code works. I have 2 classes and 1 entry point
PHP 7.2
class Base{
public function check(){
return $this->checkUnexist();
}
}
class Main extends Base
{
public function checkUnexist()
{
return 'UNEXIST METHOD CALLED';
}
}
$main = new Main();
echo $main->check();
Expected result something like called method unexist. But it calls method from child class with "this". Why? And where i can read about this issue ?
Trying to access child values from base(parent) class is a bad design. What if in the future someone will create another class based on your parent class, forget to create that specific property you are trying to access in your parent class?
As per my understanding, When you extend the class the child class have all the property, methods available for the Main class object, which are accessible outside the class.
So when you created an object of Main class your class internally looks like
class Main
{
public function checkUnexist()
{
return 'UNEXIST METHOD CALLED';
}
public function check(){
return $this->checkUnexist();
}
}
the check method exists and you will get the response. Try to make the method checkUnexist private or protected you will see the difference.

Abstract class cannot be implemented? (PHP 5.2.9)

do I have something wrong in my code or I really cannot implement interface in the abstract class? My code is not working and PHP throws an error:
Fatal error: Class 'Blah' not found
My code:
interface IBlah {
public function Fun();
}
abstract class Blah implements IBlah {
public function FunCommon() {
/* CODE */
}
abstract public function Fun();
}
class Koko extends Blah {
public function Fun() {
/* CODE */
}
}
When I'll change my code to following, now it works:
abstract class Blah {
public function FunGeneral() {
/* CODE */
}
abstract public function Fun();
}
Am I doing anything wrong? Thank you very much.
EDIT: 2014-04-01
I'm sorry #raina77ow, I was too rash. Your answer is correct and it helped me very much - I understood interface x abstract class and your advice will be really helpful in the future (my +1 for you still remains), but I tried it on another machine. Today, when I came to work and I apply your advice, the error still showed up.
I'd like to give you additional information. At the first, I removed "abstract public function Fun();" from my abstract class according to your advice. The second thing is that my interface and abstract class are in one PHP file and class Koko is in another one (if I move class Koko into the same file as interface and abstract class, no error is thrown).
I tried to print declared interfaces - get_declared_interfaces(), and declared classes - get_declared_classes(), and interface IBlah is printed out, but nor Blah neither Koko are printed out.
And When I change declaration of abstract class implementing interface only to abstract class (as I described above), Iblah and Blah and Koko are printed out all of them.
There's no need declaring an abstract function in an abstract class that's already declared in the interface it implements - you'll get an error (in PHP 5.2, looks like PHP 5.3 treats it a bit differently):
Can't inherit abstract function IBlah::Fun() (previously declared
abstract in Blah)
Solution: just drop this declaration from an abstract class altogether - this...
interface IBlah {
public function Fun();
}
abstract class Blah implements IBlah {
public function FunCommon() {}
}
class Koko extends Blah {
public function Fun() {}
}
... is a valid code both in PHP 5.2 and PHP 5.3, and Koko objects will be treated as IBlah ones. That's easy to check:
function t(IBlah $blah) {
var_dump($blah);
}
t(new Koko()); // object(Koko)#1 (0) {}

Access to inherited children's variables of abstract class from another children of same abstract class

So, I have folowing problem:
I have abstract class with multiple children of this abstract class.
In my opinion, the best explanation is an example:
abstract class AbstractClass
{
public $varialbe = false;
abstract function process();
}
class Child1 extends AbstractClass
{
public function process()
{
//some code here
}
}
class Child2 extends AbstractClass
{
public function process()
{
//!!!Problem is here = Fatal error: Cannot instantiate abstract class AbstractClass
$child1 = new Child1();
//I need something like this:
$child1->varialbe = $this->variable;
$child1->process();
}
}
$child2 = new Child2();
$child2->process();
Thanks for help!
Your code works for me! I do not get a fatal error.
The only thing I get is a notice because of the typo inside $this->variable in the child2 class. The original variable is incorrectly spelled "varialbe", but used consistently.
Fixing the typo lets the code run completely error-free.
So you fail to demonstrate the problem. Update your question if you find why the issue isn't included in your code. It must be somewhere else.
And make sure you actually run your code before using it as an example, and that it has the problem you describe.

why do we still need parent constructor when controller class extends a parent controller?

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.

'Fatal error call to private method' but method is protected

First time extending a class in PHP and I'm getting a fatal error that says the method is private when it's not. I'm sure it's something elementary, but I've studied books and forums, and I just can't pin down what I've done to generate this error. Any help greatly appreciated. Details below:
Error message:
Fatal error: Call to private method testgiver::dbConnect() from context 'testprinter' in /root/includes/classes/testprinter.php on line 726
Line 726 of testprinter in the code below:
private function buildquestionarray()
{
$query = "etc etc";
**$conn = $this->dbConnect('read');
$result = $conn->query($query);
...
Testprinter extends testgiver. Here's the extension of the class:
require_once('testgiver.php');
class testprinter extends testgiver
{...
And the declaration of the method in testgiver:
protected function dbConnect($userconnecttype)
{...
Thanks again!
As already Alexander Larikov said that you can't access protected methods from class instance but not only protected methods but also you can't access private methods from class instance. To access a protected method of a parent class from the instance of a subclass you declare a public method in the subclass and then call the protected method of the parent class from the public method of the subclass, i.e.
class testgiver{
protected function dbConnect($userconnecttype)
{
echo "dbConnect called with the argument ".$userconnecttype ."!";
}
}
class testprinter extends testgiver
{
public function buildquestionarray() // public instead of private so you can call it from the class instance
{
$this->dbConnect('read');
}
}
$tp=new testprinter();
$tp->buildquestionarray(); // output: dbConnect called with the argument read!
DEMO.
You can't access protected methods from class instance. Read documentation which says Members declared protected can be accessed only within the class itself and by inherited and parent classes
The Alpha, great write-up!
I feel like I've almost got it where I want it, but am getting
Fatal Error, call to undefined method NameofClass::myFunction() in line 123456
Is there something I am missing here?
My original class, and the extending class are both in the same .php file, but the call to myFunction is happening in a different file. Is that not allowed?
NOTE: I would put this in a comment, but the system won't let me include comments until I have a reputation of 50.

Categories