I have a few questions:
so, I have a class A as follows:
class A {
protected $ _blah = 'blah';
public __construct {
$this-> setPath ('test');
new B;
}
public setPath ($ path) {
$ This -> _ blah = $ path;
}
}
I have a Class B as follows:
class B extends A {
`echo $ this -> _ blah`;
}
nah, why is the output: 'blah' and not 'test' in class B.
however, I have changed the variable in class A to 'test' before my instance of class B.
From the code you posted, the problem is likely because you are calling $This instead of $this.
For reference, have a look at how PHP handles object inheritance. Because variables are case sensitive, you are not actually changing the property of your class in the posted code.
A better example would be the following:
class A
{
public $property = 'foo';
}
class B extends A
{
public function __construct()
{
$this->property = 'baz';
}
}
// 'foo';
echo A::$property;
$b = new B;
// 'baz'
echo $b->property;
Related
In the sample code below, the method test() in parent class Foo is overridden by the method test() in child class Bar. Is it possible to call Foo::test() from Bar::test()?
class Foo
{
$text = "world\n";
protected function test() {
echo $this->text;
}
}// class Foo
class Bar extends Foo
{
public function test() {
echo "Hello, ";
// Cannot use 'parent::test()' because, in this case,
// Foo::test() requires object data from $this
parent::test();
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Use parent:: before method name, e.g.
parent::test();
See parent
parent::test();
(see Example #3 at http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php)
Just set visibility levels at $text property.
private $text = "world\n";
Calling a parent method may be considered bad practice or code smell and may indicate programming logic that can be improved in a way, that the child doesn't have to call the parent. A good generic description is provided by Wikipedia.
An implementation without calling parent would look like:
abstract class Foo
{
$text = "world\n";
public function test() {
$this->test_child();
echo $this->text;
}
abstract protected function test_child();
}// class Foo
class Bar extends Foo
{
protected function test_child() {
echo "Hello, ";
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Judging by your comments on the pastebin, I'd say you can't.
Maybe if you had something like this?
class foo {
public function foo($instance = null) {
if ($instance) {
// Set state, etc.
}
else {
// Regular object creation
}
}
class foo2 extends foo {
public function test() {
echo "Hello, ";
// New foo instance, using current (foo2) instance in constructor
$x = new foo($this);
// Call test() method from foo
$x->test();
}
}
I have large class foo, that I want to split to two separate classes (and files);
My class foo uses contruct function and noumerous $this references.
I need a second class bar to be an extension for original foo class, so I could still use contruction with additional parameter if to include bar class;
$includeBar = true;
$foo = new foo($config, $includeBar);
I've tried putting it this way:
Class bar extends foo {
public function barFunction(){
//some function of bar
}
}
Class foo {
public function __construct($config, $includeBar = true) {
if ($includeBar) {
include_once 'bar.php';
}
}
}
But when I call:
$foo = new foo($config, true);
$foo->barFunction();
It fails, saying
PHP Fatal error: Uncaught Error: Call to undefined method foo::barFunction()
What am I doing wrong? pls help, got stuck
It should be the other way round.
Bar is your base class, that contains all the methods that every sub class also needs. Foo is the extention, the extras, so Foo extends Bar.
<?php
// file bar.php
Class Bar {
public function __construct($config) {
$this->config = $config;
}
public function barFunction() {
echo "I'm everybody ".$this->config['msg'];
}
}
// file foo.php
require_once('bar.php');
Class Foo extends Bar {
public function fooOnly() {
echo "I'm foo ".$this->config['msg'];
}
}
// consuming file index.php
include('foo.php');
$config = array('msg'=>'and I need coffee');
$foo = new foo($config);
$foo->barFunction(); // we can call this, because foo extends bar
// this won't work:
$bar = new Bar($config);
$bar->fooOnly();
// but this:
$bar->barFunction();
$foo->fooOnly();
(all the includes/requires can be omitted when using a proper autoloader!)
If you want reuse class methods or separate class method implementation I think you can use trait and then you can use keyword use to require functions to your class.
For example:
<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>
The above example will output:
Hello World!
Consider the following snippet:
Class A {
private $a = 'foo';
public function F() {
return $this->a;
}
}
Class B extends A {
private $a = 'bar';
}
echo (new B)->F();
The result is foo. Well, it's a fait accompli that php works this way. But I wonder why. If in parent's method F() declaration I use pseudo-variable $this, it refers to object context. So when I call child inherited method F() $this variable means current instance of B with private $a = 'bar', doesn't it?
Update
Thanks AbraCadaver for your reply.
One circumstance is still unclear for me: if $this variable is an object of B during call of F(), how can it access parent's private member?
Did I understand correctly that $this within parent's method implementation is something similar to:
public function F(B $obj) {
return $obj->a;
}
So interpreter checks property visibility from parent class and in case of private scope it subsitutes B $obj for A $obj
From PHP: Visibility:
Members declared
protected can be accessed only within the class itself and by
inherited and parent classes. Members declared as private may only be
accessed by the class that defines the member.
In your example, regardless of the object being of class B, class A cannot access a private property of another class.
Also, if B has a protected property, that cannot override the class A property because it is private.
Both your example and the following yield foo:
Class A {
private $a = 'foo';
public function F() {
return $this->a;
}
}
Class B extends A {
protected $a = 'bar';
public function F() {
return parent::F();
}
}
echo (new B)->F();
However, if class A is also protected then it can be overridden by class B and class A has access to the property in class B.
Yields bar:
Class A {
protected $a = 'foo';
public function F() {
return $this->a;
}
}
Class B extends A {
protected $a = 'bar';
public function F() {
return parent::F();
}
}
echo (new B)->F();
class A {
protected $a;
// SOME CODE
}
class B extends A {
// SOME CODE
}
How can i edit the protected value of the variable $a inside the B class ?
I'm trying to use parent::$a = "Some Value" but doesn't work.
protected instance properties, those which where not declared using static, can be accessed in subclasses using $this :
class A {
protected $a;
// SOME CODE
}
class B extends A {
// SOME CODE
public function edit($val) {
$this->$a = $val;
echo "a is now {$this->a}\n";
}
}
call:
$b = new B();
$b->edit('foo'); // a is now foo
Refer to the manual, especially the examples.
class B extends A {
public function foo($val)
{
$this->a = $val;
}
}
quite simple :)
Remember that
Members declared protected can be accessed only within the class
itself and by inherited and parent classes
from php manual
This is what I have in foo.php
class Foo
{
public $foo = NULL;
public $foo2 = NULL;
public function setFoo ($foo, $foo2)
{
$this->foo = $foo;
$this->foo2 = $foo2'
}
}
This is what I have in foo3.php
class Foo3 extends Foo
{
public $foo3 = NULL;
public function setFoo3 ($foo3)
{
$this->foo = $foo3;
}
}
This is how I require it in my third file run.php:
require_once "foo.php";
require_once "foo3.php";
$foo = new Foo();
$foo->setFoo3("hello");
I get this error:
Fatal error: Call to undefined method Foo::setFoo3()
I'm not sure if the problem is how I'm requiring them. Thanks.
In your example, you are instantiating Foo, which is the parent and has no knowledge of the method setFoo3(). Try this:
class Foo3 extends Foo
{
...
}
require_once "foo.php";
require_once "foo3.php";
$foo = new Foo3();
$foo->setFoo3("hello");
At the first, in your foo.php shouldn't mark your fields public, because you set those values inside setFoo($foo1, $foo2) method. Instead, you may have something like:
<?php
class Foo
{
private $foo1;
private $foo2;
public function setFoo($foo1, $foo2) {
$this->foo1 = $foo1;
$this->foo2 = $foo2;
}
}
Then you should add extends keyword when declaring class Foo3, and another thing you need to include extending class file in the beginning of the file. In your case you may have something like the following in your foo3.php file:
<?php
require_once "foo.php";
class Foo3 extends Foo
{
public function setFoo3($foo3) {
$this->setFoo($foo3, "some foo3 specific value"); // calling superclass method
}
}
then you can create an instantiate of a Foo3 class in your run.php like so:
<?php
require_once "foo3.php";
$foo3 = new Foo3();
$foo3->setFoo3("bar");
and my advice, you should read a little about OOP techniques ;)
Of course that doesn't work. You've created a Foo object, and then tried to call foo3 on it. But Foo doesn't have a foo3 method.