let's say I have a Human class which has the variable of $gender which doesn't have any value assigned into it. Human has a constructor with the parameter of age, gender, height and weight.
I have another class called Female which inheritance from Human but now the Female class is overriding the $gender variable with a string of Female.
When I create the object let's say $f = new Female(12, 'female', 123, 40);
How can I skip typing the female when creating the object?
I thought we need to create another new constructor in Female class which I did and in the Female class constructor's parameter I have age, gender = 'female', height and weight but this doesn't seem to work.
I tried leaving the gender part empty when creating the object or tried entering empty string such as "".
Can someone give me a hand please? Thanks a lot.
Code for my human class
class Human {
protected $age = 0;
protected $gender;
protected $height_in_cm;
protected $weight_in_kg;
function __construct($age, $gender, $heightCM, $weightKG)
{
$this->age = $age;
$this->gender = $gender;
$this->height_in_cm = $heightCM;
$this->weight_in_kg = $weightKG;
}
/**
* #return int
*/
public function getAge()
{
return $this->age;
}
/**
* #return string
*/
public function getGender()
{
return $this->gender;
}
}
Code for Female class
require_once('Human.php');
class Female extends Human{
protected $gender = 'female';
function __construct($age, $gender = 'female', $heightCM, $weightKG)
{
$this->age = $age;
$this->gender = $gender;
$this->height_in_cm = $heightCM;
$this->weight_in_kg = $weightKG;
}
}
$f = new Female(12,'female',123,40);
echo "Your gender is ". $f->getGender()."<br>";
Simply override the constructor:
class Human {
public function __construct($age, $gender, $height, $weight) {
}
}
class Female extends Human {
public function __construct($age, $height, $weight) {
parent::__construct($age, 'Female', $height, $weight);
}
}
You can just set the value in the extended class:
// If it should be possible to instantiate the Human
// class then remove the "abstract" thing at set the
// "gender" property in the constructer
abstract class Human {
protected $gender;
protected $age;
public function __construct($age) {
$this->age = $age;
}
}
class Female extends Human {
protected $gender = "Female";
}
class Male extends Human {
protected $gender = "Male";
}
Although this works, it really does not make that much sense. The class itself tells you what gender the human is, so you can just call $human instanceof Female.
$person = new Female(18);
if ($person instanceof Female) {
echo "Person is female";
}
You can simply overwrite the constructor:
abstract class Human
{
protected $age;
protected $gender;
protected $height;
protected $weight;
public function __construct($age, $gender, $height, $weight)
{
$this->age = $age;
$this->gender = $gender;
$this->height = $height;
$this->weight = $weight;
}
public function getGender()
{
return $this->gender;
}
}
class Female extends Human
{
public function __construct($age, $height, $weight)
{
parent::__construct($age, 'female', $height, $weight);
}
}
$female = new Female(12, 170, 60);
echo $female->getGender();
I think, in you constructor
__construct($var, $gender="female", $var, $var){
//rest assignment
}
should do it
alternatively, use 3 param constructor with female already set
Related
I want to have my inheritance but it outputs null. it was working but when I extends Patient to clinic it starts to output null. my teachers instruction was to have inheritance and I need help im still studying about this inheritance but its kind a complicated for me.
<?php
class Patient{
private $name;
private $age;
private $gender;
public function record($name, $age, $gender){
$this->name = $name;
$this->age = $age;
$this->gender = $gender;
}
public function getName(){
return $this->name;
}
public function getAge(){
return $this->age;
}
public function getGender(){
return $this->gender;
}
}
class Clinic extends Patient{
private $patients = [];
public function getPatients(){
return $this->patients;
}
public function assignPatient($name, $age, $gender){
$this->patients[] = new Patient($name, $age, $gender);
}
public function deletePatient($index){
unset($this->patients[$index]);
}
}
$clinic = new Clinic();
$clinic->assignPatient("Patrick star",18,"Male");
$clinic->assignPatient("SpongeBob Squarepants",17,"Male");
$clinic->assignPatient("Eugene Krab",28,"Male");
$clinic->deletePatient(1);
var_dump($clinic->getPatients());
A few things to change here. First, you called the function for a new patient record, but you use new Patient(). Rename the function to __construct to make it the class constructor. Now you can use new Patient(...).
Also, I think extending Patient in Clinic doesn't really make sense here, because you don't want to use the classes provided by Patient and extend them.
So remove extends Patient and your code should work now:
<?php
class Patient{
private $name;
private $age;
private $gender;
public function __construct($name, $age, $gender){
$this->name = $name;
$this->age = $age;
$this->gender = $gender;
}
public function getName(){
return $this->name;
}
public function getAge(){
return $this->age;
}
public function getGender(){
return $this->gender;
}
}
class Clinic {
private $patients = [];
public function getPatients(){
return $this->patients;
}
public function assignPatient($name, $age, $gender){
$this->patients[] = new Patient($name, $age, $gender);
}
public function deletePatient($index){
unset($this->patients[$index]);
}
}
$clinic = new Clinic();
$clinic->assignPatient("Patrick star",18,"Male");
$clinic->assignPatient("SpongeBob Squarepants",17,"Male");
$clinic->assignPatient("Eugene Krab",28,"Male");
$clinic->deletePatient(1);
print_r($clinic->getPatients());
Output:
Array
(
[0] => Patient Object
(
[name:Patient:private] => Patrick star
[age:Patient:private] => 18
[gender:Patient:private] => Male
)
[2] => Patient Object
(
[name:Patient:private] => Eugene Krab
[age:Patient:private] => 28
[gender:Patient:private] => Male
)
)
Tested on PHP 7.4 and PHP 8.0
I am currently learning OOP concepts. I have used CodeIgniter, I know it has OOP concepts but I don't understand how it works. I just use the methods in the documentation.
I am now on the inheritance part.
Here is my code:
<?php
class Artist {
public $name;
public $genre;
public $test = 'This is a test string';
public function __construct(string $name, string $genre) {
$this->name = $name;
$this->genre = $genre;
}
}
class Song extends Artist {
public $title;
public $album;
public function __construct(string $title, string $album) {
$this->title = $title;
$this->album = $album;
}
public function getSongArtist() {
return $this->name;
}
}
$artist = new Artist('Joji Miller', 'Lo-Fi');
$song = new Song('Demons', 'In Tounges');
echo $song->getSongArtist(); // returns nothing
From what I understand inheritance will let me access properties and methods from the parent class.
In my example I have instantiate the Artist. So now I have Joji Miller as artist name.
Now, if I instantiate the Song class, I thought that I can access the artist name since I am extending the Artist class. But it is just empty.
Would you help me understand why it is not getting the artist name?
Hope I explained myself clearly. Thankyou..
Heh. Learning "oop principles" from CodeIgniter is like going to North Korea to study democracy. And you have already learned the wrong things.
The extends keyword should be read as "is special case of". As in class Admin extends User means that the admin instance is a more specialized case of generic user.
And that's where you are wrong. Song is not a subtype of an artist.
Instead the song has an artist, which performs it. As in:
$artist = new Artist('Freddie Mercury');
$song = new Song('Another One Bites the Dust', $artist);
echo $song->getArtist()->getName();
Another bad practice, that you seem to have picked up: stop defining class variables as public. That breaks the encapsulation. Instead those values should be assigned using methods, because then you will e able top track, format and validate those values.
First of all in your case you have not the best example of inheritance...
And it leads to confusion...
I'd rather advise you to have in base class base behavior related to all descendants, like here.
Base class:
<?php
class SomethingWithName
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
}
Your classes:
class Artist extends SomethingWithName
{
private $genre;
public function __construct(string $name, string $genre)
{
parent::__construct($name);
$this->genre = $genre;
}
public function getGenre(): string
{
return $this->genre;
}
}
class Song extends SomethingWithName
{
private $album;
private $artist;
public function __construct(string $name, string $album, Artist $artist)
{
parent::__construct($name);
$this->album = $album;
$this->artist = $artist;
}
public function getAlbum(): string
{
return $this->album;
}
public function getArtist(): Artist
{
return $this->artist;
}
}
Result:
$a = new Artist('Joji Miller', 'Lo-Fi');
$s = new Song('Demons', 'In Tounges', $a);
var_export([
$s->getName(), // Demons
$s->getAlbum(), // In Tounges
$s->getArtist()->getName(), // Joji Miller
$s->getArtist()->getGenre(), // Lo-Fi
]);
That's because when defining the Song class's __construct() function you are overriding the Artist's __contruct() function. Which is the function that gets called when you do $song = new Song(...)
Using the keyword parent:: you can access the parent's classes functions.
The following works.
<?php
class Artist {
public $name;
public $genre;
public $test = 'This is a test string';
public function __construct(string $name, string $genre) {
$this->name = $name;
$this->genre = $genre;
}
}
class Song extends Artist {
public $title;
public $album;
public function __construct(string $title, string $album, string $ArtistName, string $genre) {
$this->title = $title;
$this->album = $album;
parent::__construct($ArtistName, $genre);
}
public function getSongArtist() {
return $this->name;
}
}
$artist = new Artist('Joji Miller', 'Lo-Fi');
$song = new Song('Demons', 'In Tounges','Joji Miller', 'Lo-Fi');
echo $song->getSongArtist(); // returns nothing
class User{
public $name ;
public $age ;
public $height ;
public $weight ;
function __construct($name,$age,$height,$weight){
$this->age = $age;
$this->name = $name;
$this->height = $height;
$this->weight = $weight;
}
public function ispis(){
echo $this->age;
}
}
$question_array = [new User ("Ivan","22","174","68"), new
User("Luka","23","174","68") ];
$daniel = new User($question_array);
//$daniel = new User("ivan","22");
$daniel->ispis();
So when i call this function ispis() it doesn't do anything but when i echo inside function __constructor it shows correct values of everything entered. Also when i comment first three lines above //$daniel = new User("ivan","22"); line and uncomment this, ispis() works just fine. Would be nice if someone could explain to me why this is happening. Tnx in advance :)
By the looks of your code you're trying to pass two new User instances into a new user ("daniel").
So basically User is expecting 4 arguments (age, name, height, weight). You've created Luka and Ivan correctly, but you're passing those two Users as arguments when trying to create Daniel. You're giving it Luka and Ivan when it wants age, name, height and weight.
If you simply want to pass an array to the constructor, just pass it as an argument on the new instance:
<?php
class User {
public $name;
public $age;
public $height;
public $weight;
function __construct($args){
$this->age = $args['age'];
$this->name = $args['name'];
$this->height = $args['height'];
$this->weight = $args['weight'];
}
function getAge() {
return $this->age;
}
}
$question_array = [
'name' => 'Daniel',
'age' => '22',
'weight' => '174',
'height' => '68'
];
$daniel = new User($question_array);
echo $daniel->getAge(); // 22
?>
Your question appears a little ambiguous, but perhaps you want to create an object from an array of arguments.
<?php
class User {
public $name;
public $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
public function echoAge()
{
echo $this->age;
}
}
$args = ['Leonard', 21];
$bones = new User(...$args);
$bones->echoAge();
Output:
21
Robert just answered, and his method is one that i use in a personal MVC to define construct or in another way there is also this method that i use always in my MVC :P...
Btw i think Ivan you are doing some confusion with classes...
class User{
public $name ;
public $age;
public $height ;
public $weight ;
function __construct($array){
if (is_array($array)){
foreach($array as $k=>$v){
$this->$k = $v;
}
}
}
public function ispis(){
print 'NAME :' .$this->name .' AGE : ' .$this->age.' HEIGHT : ' .$this->height .' WEIGHT : ' .$this->weight.'<br>';
}
}
$arrayOne = ['name'=>"Ivan",'age'=>"22",'height'=>"174",'weight'=>"68"];
$arrayTwo = ['name'=>"Luke",'age'=>"23",'height'=>"174",'weight'=>"68"];
$ivan = new User($arrayOne);
$luka = new User($arrayTwo);
$ivan->ispis();
$luka->ispis();
Let's say I have 3 objects : "Place", "Person", "Action".
Depending on the place where is the person and the age of this person, this person can do different action.
For example :
$place->person->action->drive(); // OK if place is "parking" and "person" is 18+
$place->person->action->learn(); // OK if the place is "school" and person is less than 18.
How can I access the data about the objects "Person" and "Place" from the Action class ?
Classes examples :
class Place {
public $person;
private $name;
function __construct($place, $person) {
$this->name = $place;
$this->person = $person;
}
}
class Person {
public $action;
private $name;
private $age;
function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
$this->action = new Action();
}
}
class Action {
public function drive() {
// How can I access the person's Age ?
// How can I acess the place Name ?
}
public function learn() {
// ... Same problem.
}
}
I think I could transmit "$this" from Person to Action when I create the Action Object (ie. $this->action = new Action($this)), but what about the Place data ?
It doesn't make sense to make Person a property of Place nor Action a property of Person.
I'd be more inclined to create public getters for Person and Place's properties and either make them injectable properties of Action or at least pass them as arguments to Action's methods, eg
class Place
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
class Person
{
private $name;
private $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
public function getName()
{
return $this->name;
}
public function getAge()
{
return $this->age();
}
}
class Action
{
private $person;
private $place;
public function __constuct(Person $person, Place $place)
{
$this->person = $person;
$this->place = $place;
}
public function drive()
{
if ($this->person->getAge() < 18) {
throw new Exception('Too young to drive!');
}
if ($this->place->getName() != 'parking') {
throw new Exception("Not parking, can't drive!");
}
// start driving
}
}
I'm just learning PHP, and I'm confused about what the purpose of the __construct() method?
If I can do this:
class Bear {
// define properties
public $name = 'Bill';
public $weight = 200;
// define methods
public function eat($units) {
echo $this->name." is eating ".$units." units of food... <br />";
$this->weight += $units;
}
}
Then why do it with a constructor instead? :
class Bear {
// define properties
public $name;
public $weight;
public function __construct(){
$this->name = 'Bill';
$this->weight = 200;
}
// define methods
public function eat($units) {
echo $this->name." is eating ".$units." units of food... <br />";
$this->weight += $units;
}
}
Because constructors can do more complicated logic than what you can do in variable initialization. For example:
class Bear {
private $weight;
private $colour;
public __construct($weight, $colour = 'brown') {
if ($weight < 100) {
throw new Exception("Weight $weight less than 100");
}
if (!$colour) {
throw new Exception("Colour not specified");
}
$this->weight = $weight;
$this->colour = $colour;
}
...
}
A constructor is optional but can execute arbitrary code.
You can give dynamic variables to your class:
with:
public function __construct(name, amount){
$this->name = name;
$this->weight = amount;
}
You can use your class for "bill" and "joe" and use different values of amounts.
Also you can make sure that you class will always has all it needs, for example a working database connection: You constructor should always demand all needs:
public function __construct(database_connection){
[...]
}