what is the difference between extends and normal calling? - php

What is the difference between two codes?
Extends;
<?php
require_once 'example.class.php';
Class First extends Example
{}
?>
Normal calling;
<?php
require_once 'example.class.php';
Class First
{
public $example;
function __construct()
{
$this->example = new Example();
}
}
?>
I know some difference for example using protected pharase.
But this is not enough in my opinion.

The first one, the object First will have the same properties/functions of Example class. Like:
class Example
{
public function a()
{
}
}
class First extends Example
{
public function b()
{
}
}
if you instance two objects $ex1, $ex2:
$ex1 = new Example();
$ex1->a(); // this is valid
$ex1->b(); // this is invalid because Example doesn't have "b" function
$ex2 = new First();
$ex2->a(); // this is valid
$ex2->b(); // this is valid too, because First inherits Example members + its own
on the second code, you're creating an instance of example so you must access that variable to be able to call Example method.
one better example:
class Person
{
public $name;
public function say($message)
{
echo $this->name . " says " . $message;
}
}
class Teacher extends Person
{
public function say($message)
{
// note that Teacher has a name even this is not declared here.
echo $this->name . " says " . $message;
}
public function teach($what)
{
// note that Teacher has a name even this is not declared here.
echo $this->name . " is teaching " . $what;
}
}
See the output:
$john = new Person();
$john->name = "John Doe";
$john->say("hello world!");
/*
$john->teach("Portuguese"); // invalid, person doesn't teach anything.
*/
$chuck = new Teacher();
$chuck->name = "Chuck Norris";
$chuck->say("hello universe!");
$chuck->teach("Fighting"); // valid because Teacher has method "teach"

Extends
This is object inheritance. First inherits Example members, so First is Example.
An instance of First can call a method of Example and one of itself.
Creating an instance of Example
This just creating an object of Example. First methods can use other objects in order to achieve its goals.
I believe you need to get more in touch with object-oriented programming in order to learn more about its concepts and you'll understand things like this.

In the first example, First extends Example so it has all its methods and properties.
In your second example you are just setting a property to be an object of the class Example. At least I assume that is what you want to do because the way you wrote it, $example is only defined in the scope of the constructor so it is never available anywhere.
I assume that for your second example you would want something like:
Class First
{
protected $example;
function __construct()
{
$this->example = new Example();
}
}

jeroen is correct, but it also determines which attributes of the Example class can be accessed from the First class. For example, if the Example class has 2 methods which are private or protected, and you don't extend, the First class will not be able to access them.
Consider the following:
class Example
{
public $foo;
protected $bar;
}
Class First extends Example
{
public function __construct()
{
$this->foo = 'FOO1'; // Works because public scope
$this->bar = 'BAR1'; // Works even though scope is protected, because we extended the class
}
}
Class Second
{
public example;
function __construct()
{
$this->example = new Example();
$this->example->foo = 'FOO1'; // Works because public scope
$this->example->bar = 'BAR2'; // Fails because protected scope and we did not extend the class
}
}
// However, from the calling code, I am also limited
$first = new First();
$first->foo = 'NEW_FOO1'; // Works because public scope
$first->bar = 'NEW_BAR1'; // Fails because protected scope
$second = new Second();
$second->example->foo = 'NEW_FOO2'; // Works because public scope
$second->example->bar = 'NEW_BAR2'; // Fails because protected scope

Related

override a static variable

I have two classes (Model and User) but I have a problem so I have tried to explain it in a simple example :
class person
{
protected static $todo ="nothing";
public function __construct(){}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
protected static $todo ="studing";
}
$s = new student();
$s->get_what_todo(); // this will show the word (nothing)
//but I want to show the word (studing)
Please give me a solution but without writing any function in the student class I only want to make declarations there :) and thank you :)
The principle is called "late static binding", and was introduced in PHP 5.3.0; with the self keyword to access the property defined in the calling class within the inheritance tree, or static to access the property defined in the child class within that inheritance tree.
class person
{
protected static $todo ="nothing";
public function __construct(){}
public function get_what_todo()
{
echo static::$todo; // change self:: to static::
}
}
class student extends person
{
protected static $todo ="studying";
}
class teacher extends person
{
protected static $todo ="marking";
}
class guest extends person
{
}
$s = new student();
$s->get_what_todo(); // this will show the "studying" from the instantiated child class
$t = new teacher();
$t->get_what_todo(); // this will show the "marking" from the instantiated child class
$g = new guest();
$g->get_what_todo(); // this will show the "nothing" from the parent class,
// because $todo is not overriden in the child class
The reliable way to override a static variable is to do it by redeclaring it. Some people may suggest modifying it in the construct method, but I don't think that's reliable.
It won't reflect the changes until the class is constructed at least once. And of course, in class methods, don't forget to call the static variable using "static::" instead of "self::" when you want to always access the overridden variable.
Here's an example of what I mean:
The class Foo is the base class, the class Bar is changing the variable inside its constructor, and the class Baz is overriding the variable in its declaration.
class Foo
{
public static $a = "base";
}
class Bar extends Foo
{
function __construct()
{
self::$a = "overridden";
}
}
class Baz extends Foo
{
public static $a = "overridden";
}
echo 'Foo: ' . Foo::$a . '<br>';
echo 'Bar: ' . Bar::$a . '<br>';
echo 'Baz: ' . Baz::$a . '<br>';
new Bar();
echo 'Bar after instantiation: ' . Bar::$a;
This is the output from phptester.net
Foo: base
Bar: base
Baz: overridden
Bar after instantiation: overridden
As you can see, Bar's way of changing the variable isn't taking effect until after the constructor is called at least once.
EDIT: However, there is another way to edit a variable permanently and reliably: do it after the class declaration. This is especially handy if you only need to modify a variable and not completely override it, like for example an array. It feels a bit dirty, but in theory should work everytime.
class Foo
{
public static $a = [
'a' => 'a'
];
}
class Bar extends Foo
{
public static $a;
}
Bar::$a = Foo::$a;
Bar::$a['b'] = 'b';
echo 'Foo: ' . print_r(Foo::$a, true) . '<br>';
echo 'Bar: ' . print_r(Bar::$a, true) . '<br>';
This is the output from phptester.net
Foo: Array ( [a] => a )
Bar: Array ( [a] => a [b] => b )
EDIT 2: This last method also gets picked up by ReflectionClass::getStaticPropertyValue in my tests.
you can try set variable in construction
class person
{
protected static $todo = null;
public function __construct(){
self::$todo = "nothing";
}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
public function __construct() {
self::$todo = "student";
}
}
$s = new student();
$s->get_what_todo();
you can try set parent variable in construction
class person
{
protected static $todo = null;
public function __construct(){
self::$todo = "nothing";
}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
public function __construct() {
parent::$todo = "student";
}
}
$s = new student();
$s->get_what_todo();

PHP Sibling Class Inheritance

I'm a bit confused on whether or not this is possible. I've checked a couple of posts here on SO and they don't really explain what I'm looking for.
I have 3 classes. One main class and two classes extending that main class. (see code below). Is it possible to run a method in one of the two extended classes from it's sibling (the other extended class)?
If it's not possible, how can I change my code to accomplish what I'm doing in the example below?
DECLARATION
class A {
public function __construct() {
//do stuff
}
}
class B extends A {
private $classb = array();
public function __construct() {
parent::__construct();
//do stuff
}
public function get($i) {
return $this->classb[$i];
}
public function set($i, $v) {
$this->classb[$i] = $v;
}
}
class C extends A {
public function __construct() {
parent::__construct();
//do stuff
}
public function display_stuff($i) {
echo $this->get($i); //doesn't work
echo parent::get($i); //doesn't work
}
}
USAGE
$b = new B();
$c = new C();
$b->set('stuff', 'somestufftodisplay');
$c->display_stuff('stuff'); // <----- Displays nothing.
Your code shows an additional problem apart from the main question so there are really two answers:
No, you cannot run a method from a sibling class in another sibling class. If you need that, the method should be in the parent class. The same applies to properties.
You cannot use the value of a property from one object in another object, even if they are both of the same class. Setting a property value in one object sets its value only there as different objects can have the same properties with completely different values. If you need to share the value of a property between the objects and also be able to modify it, you should use a static property. In this case you would have to define that in the parent class, see my previous point.
So to make it work, you would need something like
class A {
private static $var = array();
public function get($i) {
return self::$var[$i];
}
public function set($i, $v) {
self::$var[$i] = $v;
}
}
class B extends A {
}
class C extends A {
public function display_stuff($i) {
echo $this->get($i); // works!
}
}
$b = new B();
$c = new C();
$b->set('stuff', 'somestufftodisplay');
$c->display_stuff('stuff');
An example.

PHP: how to access the data members of super class in subclass with the same name?

I searched everywhere but did not find any solution to this question.
Following is my code where I want to access the $myvar of the super class in the subclass but I don't know how? when I use $this keyword it accesses the variable in the same class but not the one in super class. please any help will be greatly appreciated.
<?php
class First{
protected $myvar = "First Class";
}
class Second extends First{
public $myvar = "Second Class";
function __construct(){
echo $this -> myvar;// here I want to access the $myvar of super class
}
}
$obj = new Second();
?>
Note: I can achieve the same functionality in java by using the super keyword.
You may create a custom function that returns the variables from the parent class BUT keep in mind that the variables should be "private":
class First{
private $myvar = "First Class";
protected function get_variable($var_name)
{
return $this->{$var_name};
}
}
class Second extends First{
public $myvar = "Second Class";
function __construct() {
echo parent::get_variable('myvar');
}
}
$obj = new Second();
The way you try to do this will not work, as Rizier mentioned. Maybe static properties can be useful to you (depending on your needs ofcourse)
<?php
class a {
protected static $var = 'a';
}
class b extends a {
protected static $var = 'b';
public function __construct() {
echo self::$var;
echo parent::$var;
}
}
$b = new b();
You could also reconstruct a in b. You'd be able to leverage the inheritance for methods and maybe other properties, while being able to use the default value in a-constructor.
<?php
class a {
protected $var = 'a';
}
class b extends a {
protected $var = 'b';
public function __construct() {
echo $this->var;
$a = new a();
echo $a->var;
}
}
$b = new b();
The main question I think you should answer is why you want a class to inherit from another but still want to be able to change/modify stuff in the parent. That's kinda counterproductive for the whole inheritance design.
You can't you are overwritten in when creating the sub class which inherits from the parent class. So you would have to change the name for it.
You override the parent parameter with:
public $myvar = "Second Class";
Remove this line to use the inherits from parent class or change the name of the child class parameter.

PHP new static($variable)

$model = new static($variable);
All these are within a method inside a class, I am trying to technically understand what this piece of code does. I ran around in the Google world. But can't find anything that leads me to an answer. Is this just another way of saying.
$model = new static $variable;
Also what about this
$model = new static;
Does this mean I'm initializing a variable and settings it's value to null but I am just persisting the variable not to lose the value after running the method?
static in this case means the current object scope. It is used in late static binding.
Normally this is going to be the same as using self. The place it differs is when you have a object heirarchy where the reference to the scope is defined on a parent but is being called on the child. self in that case would reference the parents scope whereas static would reference the child's
class A{
function selfFactory(){
return new self();
}
function staticFactory(){
return new static();
}
}
class B extends A{
}
$b = new B();
$a1 = $b->selfFactory(); // a1 is an instance of A
$a2 = $b->staticFactory(); // a2 is an instance of B
It's easiest to think about self as being the defining scope and static being the current object scope.
self is simply a "shortcut name" for the class it occurs in. static is its newer late static binding cousin, which always refers to the current class. I.e. when extending a class, static can also refer to the child class if called from the child context.
new static just means make new instance of the current class and is simply the more dynamic cousin of new self.
And yeah, static == more dynamic is weird.
You have to put it in the context of a class where static is a reference to the class it is called in. We can optionally pass $variable as a parameter to the __construct function of the instance you are creating.
Like so:
class myClass {
private $variable1;
public function __construct($variable2) {
$this->variable1 = $variable2;
}
public static function instantiator() {
$variable3 = 'some parameter';
$model = new static($variable3); // <-this where it happens.
return $model;
}
}
Here static refers to myClass and we pass the variable 'some parameter' as a parameter to the __construct function.
You can use new static() to instantiate a group of class objects from within the class, and have it work with extensions to the class as well.
class myClass {
$some_value = 'foo';
public function __construct($id) {
if($this->validId($id)) {
$this->load($id);
}
}
protected function validId($id) {
// check if id is valid.
return true; // or false, depending
}
protected function load($id) {
// do a db query and populate the object's properties
}
public static function getBy($property, $value) {
// 1st check to see if $property is a valid property
// if yes, then query the db for all objects that match
$matching_objects = array();
foreach($matching as $id) {
$matching_objects[] = new static($id); // calls the constructor from the class it is called from, which is useful for inheritance.
}
return $matching_objects;
}
}
myChildClass extends myClass {
$some_value = 'bar'; //
}
$child_collection = myChildClass::getBy('color','red'); // gets all red ones
$child_object = $child_collection[0];
print_r($child_object); // you'll see it's an object of myChildClass
The keyword new is used to make an object of already defined class
$model = new static($variable);
so here there is an object of model created which is an instance of class static

PHP parent:: equivalent for objects

class Second
{
// i've got to access to $variable from First instance from here
}
class First
{
public $variable;
public $SecondInstance;
public function __construct($variable)
{
$this->variable = $variable;
$this->SecondInstance = new Second();
}
}
$FirstObj = new First('example variable');
I need an equivalent for parent::$variable for objects.
Is there a possibility to do that in that way?
No, you cannot. The only way you can manage that, without extending First, is to pass "$this" to the constructor of Second:
$this->SecondInstance = new Second ($this);
Or, you can simply pass $variable to its constructor.
You mean like the parent function in PHP:
//You may find yourself writing code that refers to variables
//and functions in base classes. This is particularly true if
// your derived class is a refinement or specialisation of
//code in your base class.
//Instead of using the literal name of the base class in your
//code, you should be using the special name parent, which refers
//to the name of your base class as given in the extends declaration
//of your class. By doing this, you avoid using the name of your base
//class in more than one place. Should your inheritance tree change
//during implementation, the change is easily made by simply
//changing the extends declaration of your class.
<?php
class A {
function example() {
echo "I am A::example() and provide basic functionality.<br />\n";
}
}
class B extends A {
function example() {
echo "I am B::example() and provide additional functionality.<br />\n";
parent::example();
}
}
$b = new B;
// This will call B::example(), which will in turn call A::example().
$b->example();
?>
I would recommend you change your strucutre a little to "extend":
class second extends first{
public __construct(){
parent::__construct();
echo $this->variable;
}
}
Otherwise you will need to assign the "first" as a parent class within the variables on the second and actually access it like that:
class second{
public $first;
public function __construct($first){
$this->first = $first;
var_dump($this->first->variable);
}
}
Or of course you can also make the first class static and access it that way.

Categories