Why is the Class extend not getting private variable - php

The following code does not produce the output with the name Jock. I suspect because in the class Animal the $name is private, but the construct is public so should the subclass not be able to get the $name from the construct. I do not want to make $name public.
class Animal{
private $name;
public function __construct($name) {
$this->name = $name;
}
public function Greet(){
echo "Hello, I'm some sort of animal and my name is ", $this->name ;
}
}
class Dog extends Animal{
private $type;
public function __construct($name,$type) {
$this->type = $type;
parent::__construct($name);
}
public function Greet(){
echo "Hello, I'm a ", $this->type, " and my name is ", $this->name;
}
}
$dog2 = new Dog('Jock','dog');
$dog2->Greet();

You are right: delete the private variable or use protected in the first line of the class animal and you're fine.
class Animal{
protected $name; //see here!
public function __construct($name) {
$this->name = $name;
}
public function Greet(){
echo "Hello, I'm some sort of animal and my name is ".$this->name ;
}
}
$animal = new Animal("Gizmo");
$animal->greet(); //produces the desired result.
echo $animal->name; //this will throw an error - unable to access protected variable $name
$name won't be public since it is an argument used in the public constructor and is therefore confined to the scope of that function. The property name on the dog will be public however unless you use protected.
Dots are used to concat strings. However echo allows commas to output multiple expressions.
public function Greet(){
echo "Hello, I'm a ".$this->type." and my name is ".$this->name;
}
Also when using double quotes; you can put the variables inside the string:
public function Greet(){
echo "Hello, I'm a $this->type and my name is $this->name";
}

the private variable only accessed inside the same class, you need to use protected for the name variable in class Animal.
class Animal{
protected $name;
public function __construct($name) {
$this->name = $name;
}
public function Greet(){
echo "Hello, I'm some sort of animal and my name is ", $this->name;
}
}
class Dog extends Animal{
private $type;
public function __construct($name,$type) {
$this->type = $type;
parent::__construct($name);
}
public function Greet(){
echo "Hello, I'm a ", $this->type, " and my name is ", $this->name;
}
}
$dog2 = new Dog('Jock','dog');
$dog2->Greet();

You could use setter & getter methods to help you modify and retrieve your instance variables without needing to declare them as public.
If you are using eclipse:
Right click on the class > Source > Generate Getters & Setters
which will create functions for all of your variables as so:
public String getName(){return this.name;}
public String setName(String name){this. name = name; }
You could then use these methods to access and edit your class variables

Related

Visibility Modifiers [duplicate]

Shouldn't it generate error when i try to set the value of a property from the extended class instead of a base class?
<?php
class first{
public $id = 22;
private $name;
protected $email;
public function __construct(){
echo "Base function constructor<br />";
}
public function printit(){
echo "Hello World<br />";
}
public function __destruct(){
echo "Base function destructor!<br />";
}
}
class second extends first{
public function __construct($myName, $myEmail){
$this->name = $myName;
$this->email = $myEmail;
$this->reveal();
}
public function reveal(){
echo $this->name.'<br />';
echo $this->email.'<br />';
}
}
$object = new second('sth','aaa#bbb.com');
?>
Private variables are not accessible in subclasses. Thats what the access modifier protected is for. What happened here is that when you access a variable that doesn't exist, it creates one for you with the default access modifier of public.
Here is the UML to show you the state:
Please note: the subclass still has access to all the public and protected methods and variables from its superclass - but are not in the UML diagram!

PHP Class Inheritance private property construct

Im taking a 3rd year module on webDesign focusing on OOP concepts which im struggling to master, but slowly getting there...
An Assignment Question Reads As Follows:
I coded thequestions above and I got the correct output but:
I am unsure if the way I coded the greet() method in question A & B is correct?
2.The constructor and related properties inside the sub class for question B, I have my doubts whether those are correctly coded...even though I'm getting correct output, Please see comments in code
I fail to see the benefit of extending the class, perhaps I don't see it because I Went about it the wrong way..?
Any advice appreciated, code follow below.
A)
class Animal{
private $name;
public function __construct($dogName){
$this->name = $dogName;
}//construct
public function greet(){
$sting = "Hello I'm some sort of animal and my name is .$this->name.";
return $sting;
}//function
}//class
$animal = new Animal('Jock');
echo $animal->greet();
B - SubClass
class Dog extends Animal
{
private $animalType;
public function __construct($animalType, $dogName){
$this->$animalType = $animalType;
$this->dogName = $dogName; //IS THIS LINE CORRECT, IF YES WHY SHOULD I USE IT AGAIN IN PARENT::_CONSTRUCT?
//Call Animal Constructor To Finish
parent::__construct($dogName);
}//constructor
public function greet($value1, $value2){
$this->animalType = $value1;
$this->dogName = $value2;
$string = "Hello, I'm a ". $value1. " and my name is ". $value2;
return $string;
}
}
$dog = new Dog('Dog', 'Jock');
echo $dog->greet('Dog', 'Jock');
Problems with your code:
1) Why would you have Dog::$animalType field? The purpose of extending generic Animal class is to make it rather specific with Dog subclass. Instead, just use strtolower(__CLASS__) for animal type.
2)Dog::greet() method doesn't need any arguments. It can clearly use $this->dogName.
3) You should name both name fields as Animal::$name and Dog::$name. That way, the sub-class will inherit from its parent class and override the values. Instead you have introduced additional field which does the same thing, and breaks the logical relation between parent and child classes.
4) Both parent and child classes should have same signatures for methods with the same name, so that inheritance could have a purpose. And since child classes inherit parent's classes as they are, there is no need to re-define them (in your case, the constructor).
class Animal
{
private $name; // can't be private (unless you use a getter), if you want to extend it
public function __construct($name)
{
$this->name = $name;
}
public function greet()
{
return "Hello I'm some sort of animal and my name is " . $this->getName();
}
protected function getName()
{
return $this->name;
}
}
class Dog extends Animal
{
public function greet()
{
return "Hello, I'm a " . strtolower(__CLASS__) . " and my name is " . $this->getName();
}
}
$animal = new Animal('Cow');
echo $animal->greet();
$dog = new Dog('Max');
echo $dog->greet();
I think that the question is worded slightly incorrectly. I think that it wants you make the properties protected rather than private to extend the class (otherwise you would have to re-define the same properties in the subclass).
If this is the case, here is an example that shows class inheritance:
class Animal
{
protected $name;
public function __construct($name)
{
$this->name = $name;
}
public function greet()
{
return "Hello I'm some sort of animal and my name is {$this->name}.";
}
}
$animal = new Animal('Jock');
echo $animal->greet();
class Dog extends Animal
{
public function greet()
{
return "Hello I'm a dog and my name is {$this->name}.";
}
}
$dog = new Dog('Jock');
echo $dog->greet();
You can see that we don't need to redefine the property $name and the constructor. The class Dog knows it's a dog, so we don't need to tell it that - we just adjust our greet method accordingly. This shows how we can access the protected property $name from Dog, and shows how we have overridden the greet method in Dog.
I hope this sheds some light on the subject.
I think you don't need the constructer in Dog class. The greet function looks wrong. I think you have to use the name from Animal class by using a name getter (getName).
class Animal
{
private $name;
public function __construct($name)
{
$this->name = $name;
}//construct
public function greet()
{
$sting = "Hello I'm some sort of animal and my name is " . $this->getName();
return $sting;
}//function
public function getName() {
return $this->name;
}
}//class
$animal = new Animal('Jock');
echo $animal->greet();
class Dog extends Animal
{
public function greet()
{
$string = "Hello, I'm a dog and my name is " . $this->getName();
return $string;
}
}
$dog = new Dog('Jock');
echo $dog->greet();
Another way of doing this
<?php
class Animal{
protected $name;
public function __construct($dogName){
$this->name = $dogName;
}//construct
public function greet(){
$sting = "Hello I'm some sort of animal and my name is .$this->name.";
return $sting;
}//function
}//class
$animal = new Animal('Jock');
echo $animal->greet();
class Dog extends Animal
{
private $animalType;
public function __construct($animalType,$dogname){
$this->animalType = $animalType;
parent::__construct($dogname);
}
public function greet(){
echo "Hello, I'm a ".$this->animalType. " and my name is ".$this->name;
}
}
$dog = new Dog('Dog', 'New Dog');
echo $dog->greet();
?>

Why is PHP private variables working on extended class?

Shouldn't it generate error when i try to set the value of a property from the extended class instead of a base class?
<?php
class first{
public $id = 22;
private $name;
protected $email;
public function __construct(){
echo "Base function constructor<br />";
}
public function printit(){
echo "Hello World<br />";
}
public function __destruct(){
echo "Base function destructor!<br />";
}
}
class second extends first{
public function __construct($myName, $myEmail){
$this->name = $myName;
$this->email = $myEmail;
$this->reveal();
}
public function reveal(){
echo $this->name.'<br />';
echo $this->email.'<br />';
}
}
$object = new second('sth','aaa#bbb.com');
?>
Private variables are not accessible in subclasses. Thats what the access modifier protected is for. What happened here is that when you access a variable that doesn't exist, it creates one for you with the default access modifier of public.
Here is the UML to show you the state:
Please note: the subclass still has access to all the public and protected methods and variables from its superclass - but are not in the UML diagram!

Calling to a member function on a non-object Error

i'm having a trouble at the moment that i'm trying to access from a method of Wolf class to other method of Dog class. That's the code:
index.php
require_once 'Wolf.php';
require_once 'Dog.php';
class StackOverflowExample{
public static function run(){
$dog = new Dog("Cokey");
$wolf = new Wolf("Wolfenstein");
$wolf->hunt();
}
}
StackOverflowExample::run();
Wolf.php
class Wolf {
private $_name;
public function __construct($name){
$this->_name = $name;
}
public function hunt(){
return $dog->setLife(0);
}
}
Dog.php
class Dog {
private $_name;
private $_life= 100;
public function __construct($name){
$this->_name = $name;
}
public function setLife($life){
$this->_life = $life;
}
public function getLife(){
return $this->_life;
}
}
It gives me the next errors:
· Undefined variable: dog
· Call to a member function setLife() on a non-object
I have spent two days searching and I still having no way to fix.
Thanks you and sorry for my bad english.
What you should do is to pass $dog around, in the hunt method, like this:
public function hunt(Dog $dog){
return $dog->setLife(0);
}
You get the ability to validate that the dog variable is an instance of the expected class.
This method of passing objects around is called dependency injection.
If you want to pass around all sorts of animals you need to use another concept called inheritance:
abstract class Animal
{
public $_life;
public function setLife($life){
$this->_life = $life;
}
public function getLife(){
return $this->_life;
}
}
class Dog extends Animal
{
private $_name;
public function __construct($name){
$this->_name = $name;
}
}
class Wolf {
private $_name;
public function __construct($name){
$this->_name = $name;
}
public function hunt(Animal $animal){
return $animal->setLife(0);
}
}
Notice that the common methods and variables live in the parent class, and that you can create as many types as animals as you want.
If you follow this example you should find a way to declare the animal's name variable in the Animal class so you don't have to redefine it in all subclasses ;)
Replace
$dog->setLife(0);
by
Dog::setLife(0);

PHP Calling To Object From Another Object

I've been programming mainly with JAVA and have written procedural programs in PHP, but now I'm try to write some OOP bases programs in PHP and I'm facing a problem.
I've got two files , Zoo.php and Dog.php , each contains a class.
Dog.php:
<?php
class Dog {
private $name;
private $color;
public function __construct($name,$color) {
$this->name = $name;
$this->color = $color;
}
public function getName(){
return $this->name;
}
public function getColor(){
return $this->color;
}
}
And Zoo.php:
<?php
class Zoo {
private $name;
private $dogs;
public function __construct($name) {
$this->name = $name;
$dogs = array();
}
public function addDog($dogName,$dogColor){
$dog = new Dog($dogName,$dogColor);
array_push($this->dogs,$dog);
}
public function getAllDogs(){
var_dump($dogs);
}
}
echo "start";
$z = new Zoo("test_zoo");
$z->addDog("blackie","black");
$z->getAllDogs();
The code above outputs :
Fatal error: Class 'Dog' not found in C:\wamp\www\Zoo.php on line 13
I'd like to know what's wrong with the code above and how creating an object instance within another object should be done in PHP. Thanks in advance.
I gues you are not including Dog class.
<?php
include "Dog.php";
class Zoo {
/* ... */
}
Or you can use autoloading to auto include any class by default.
It's not about OOP. Just you forgot to include Dog file to use it you Zoo class :
<?php
include 'Dog.php'; // or whatever path
class Zoo { ...
Everything else should be ok and seems to be a good use of PHP OOP btw. :)
You haven't included your Dog.php in your Zoo.php. Therefore you can't create an new instance.
Just above class Zoo add this:
include("Dog.php");
class Zoo {
All you need to return function .
Three mistakes here, u'll see all of them in my code . Constructer nothing return , behave like void , so we need a method that returns dog specification.If you wanna use the classes in separate file, so u've to use php method that "include" or "require" or "require_once" etc ( see the difference of this method)
<?php
class Dog {
private $name;
private $color;
public function __construct($name,$color) {
$this->name = $name;
$this->color = $color;
}
public function getName(){
return $this->name;
}
public function getColor(){
return $this->color;
}
public function getDogs(){
return array("name"=>$this->name,"color"=>$this->color);
}
}
class Zoo extends Dog{
private $name;
private $dogs=array();
public function __construct($name) {
$this->name = $name;
$dogs = array();
}
public function addDog($dogName,$dogColor){
$dog = new Dog($dogName,$dogColor);
array_push($this->dogs,$dog->getDogs());
}
public function getAllDogs(){
var_dump($this->dogs);
}
}
echo "start";
$z = new Zoo("test_zoo");
$z->addDog("blackie","black");
$z->getAllDogs();
?>

Categories