php work out total area of a certain shape (maths) - php

I am trying to make a php product which works out area and perimeter of different shapes. There are different shapes e.g. square, rectangle, circle, triangles etc.
I currently have Total Area of all shapes, count how many shapes were worked out, highest perimeter working and there is the code for it,
edit2:
abstract class Shapes
{
protected $name;
protected $colour;
function __construct($n, $c)
{
$this->name = $n;
$this->colour = $c;
}
abstract public function area();
abstract public function perimeter();
public function printShape()
{
}
thanks

In your Shapes class, create a getter (method) called getName that returns the $name property.
e.g.
abstract class Shapes
{
protected $name;
protected $colour;
function __construct($n, $c)
{
$this->name = $n;
$this->colour = $c;
}
abstract public function area();
abstract public function perimeter();
public function printShape()
{
print "<h6>The area of the " . $this->colour . " " . $this->name . " is " . $this->area(
) . " and the perimeter is " . $this->perimeter() . "</h6>";
}
public function getName()
{
return $this->name;
}
}

Related

Extened class not able to get data from parent class

I am trying to use a display function in my extened class that first fetches a display function in the parent class. It however does not display the variable in the echo statement. The gameType (In this case "One-day") does not display.
<?php
class Cricket
{
protected $gameType;
function __construct($gameType)
{
$this->gameType=$gameType;
}
function display()
{
echo 'The cricket match is a ' . $this->gameType . " match";
}
}
class Bowler extends Cricket
{
public $type;
public $number;
function __construct($type,$number)
{
$this->type=$type;
$this->number=$number;
parent::__construct($this->gameType);
}
function display()
{
parent:: display();
echo " with " . $this->number . " " . $this->type . " bowler";
}
}
$one = new Cricket("day-night");
$one->display();
echo'<br>';
$two = new Cricket("day-night");
$two = new Bowler("left-hand","2");
$two->display();
?>
The process of instantiating your Bowler class will in fact, as is implied by calling the parents constructor parent::__construct();, create a brand new Cricket class as well as the Bowler class.
So attempting to access a property of this newly created Cricket class makes no sense.
So when you instantiate the Bowler class you will also have to pass any data that the Cricket class requires for it's successful construction.
So for example
<?php
class Cricket
{
protected $gameType;
function __construct($gameType)
{
$this->gameType=$gameType;
}
function display()
{
echo 'The cricket match is a ' . $this->gameType . " match";
}
}
class Bowler extends Cricket
{
public $type;
public $number;
function __construct($gameType, $type, $number)
{
$this->type=$type;
$this->number=$number;
parent::__construct($gameType);
}
function display()
{
parent:: display();
echo " with " . $this->number . " " . $this->type . " bowler";
}
}
$two = new Bowler('day-night', "left-hand","2");
$two->display();

PHP multiple __toString methods, switched in the runtime

I need different __toString() for the same class.
Example
I have the Person class that contains a firstname and a surname. According to current context I wish to display it with different order, formatting etc. Imagine three scenarios:
the firstname comes first, followed by space and surname Thomas Müller
the surname comes first and uppercased, followed by space and the firstname MÜLLER Thomas
the surname comes first, followed by comma, then space and the firstname Müller, Thomas
I can create public methods for each display.
<meta charset='utf-8'/>
<?php
class Person
{
protected $firstname;
protected $surname;
public function __construct($firstname, $surname)
{
$this->firstname = $firstname;
$this->surname = $surname;
}
public function toStringWithFirstnameFirst()
{
return $this->firstname . " " . $this->surname;
}
public function toStringWithSurnameFirstUppercase()
{
$surnameConverted = mb_convert_case($this->surname, MB_CASE_UPPER, "UTF-8");
return $surnameConverted . " " . $this->firstname;
}
public function toStringWithSurnameFirstAndFirstnameAfterComma()
{
return $this->surname . ", " . $this->firstname;
}
}
$person = new Person("Thomas", "Müller");
echo $person->toStringWithFirstnameFirst() . "<br/>";
echo $person->toStringWithSurnameFirstUppercase() . "<br/>";
echo $person->toStringWithSurnameFirstAndFirstnameAfterComma() . "<br/>";
?>
But I stuck with DescriptiveButVeryLongToStringMethodNames.
I wish to have simply echo $person; in the code.
Solution: store the class state in the static members
My first solution is to place switch-case inside __toString() method. Conditional statement depends on the class state stored in the static variable self::$chosenToStringMethod. So I need static method to set the class state and also class constants that serve as enums.
<meta charset='utf-8'/>
<?php
class Person
{
protected $firstname;
protected $surname;
const PRINT_FIRSTNAME_FIRST = 1;
const PRINT_SURNAME_FIRST_UPPERCASE = 2;
const PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA = 3;
static private $chosenToStringMethod;
public function __construct($firstname, $surname)
{
$this->firstname = $firstname;
$this->surname = $surname;
}
static public function setToStringMethod($choice)
{
self::$chosenToStringMethod = $choice;
}
private function toStringWithFirstnameFirst()
{
return $this->firstname . " " . $this->surname;
}
private function toStringWithSurnameFirstUppercase()
{
$surnameConverted = mb_convert_case($this->surname, MB_CASE_UPPER, "UTF-8");
return $surnameConverted . " " . $this->firstname;
}
private function toStringWithSurnameFirstAndFirstnameAfterComma()
{
return $this->surname . ", " . $this->firstname;
}
public function __toString()
{
switch (self::$chosenToStringMethod) {
case self::PRINT_FIRSTNAME_FIRST:
return $this->toStringWithFirstnameFirst();
break;
case self::PRINT_SURNAME_FIRST_UPPERCASE:
return $this->toStringWithSurnameFirstUppercase();
break;
case self::PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA:
return $this->toStringWithSurnameFirstAndFirstnameAfterComma();
break;
default:
return "No __toString method set";
break;
}
}
}
$person = new Person("Thomas", "Müller");
echo $person . "<br/>";
Person::setToStringMethod(Person::PRINT_FIRSTNAME_FIRST);
echo $person . "<br/>";
Person::setToStringMethod(Person::PRINT_SURNAME_FIRST_UPPERCASE);
echo $person . "<br/>";
Person::setToStringMethod(Person::PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA);
echo $person . "<br/>";
?>
I see some disadvantages of this solution:
Person class is getting heavy
switch-case statements can hide some mistakes
I wish Person class containing only its own functionality not all kinds of toStrings. I would rather have some pattern that can dynamically inject __toString().
ok, I assume the reason, why you're asking, is that you'd like to keep things clean but there's no way to set __toString() method to an existing object, so the best solution would be to split functionality
first create a PersonRender:
class PersonRender
{
const PRINT_FIRSTNAME_FIRST = 1;
const PRINT_SURNAME_FIRST_UPPERCASE = 2;
const PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA = 3;
static public $chosenToStringMethod;
private $person;
public function __construct($person)
{
$this->person = $person;
}
public function render()
{
switch (self::$chosenToStringMethod)
{
case self::PRINT_SURNAME_FIRST_UPPERCASE :
return $this->toStringWithSurnameFirstUppercase();
case self::PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA :
return $this->toStringWithSurnameFirstAndFirstnameAfterComma();
default :
return $this->toStringWithFirstnameFirst();
}
}
private function toStringWithFirstnameFirst()
{
return "{$this->person->firstname} {$this->person->surname}";
}
private function toStringWithSurnameFirstUppercase()
{
$surnameConverted = mb_convert_case($this->person->surname, MB_CASE_UPPER, "UTF-8");
return "{$surnameConverted} {$this->person->firstname}";
}
private function toStringWithSurnameFirstAndFirstnameAfterComma()
{
return "{$this->person->surname}, {$this->person->firstname}";
}
}
and then the Person class:
class Person
{
public $firstname, $surname;
public function __construct($firstname, $surname)
{
$this->firstname = $firstname;
$this->surname = $surname;
}
public function __toString() {
$render = new PersonRender($this);
return $render->render();
}
}
and a little test:
$person = new Person('Foo', 'Bar');
echo $person;
echo '<hr />';
PersonRender::$chosenToStringMethod = PersonRender::PRINT_SURNAME_FIRST_UPPERCASE;
echo $person;
EDIT 1
to keep the code clean, the Person entity class should of course have private props firstname and surename and methods set and get
In my opinion the most clean way would be to just provide getter for firstname and surname and manually assemble the strings where you need them. In your current solutions you are just polluting your workspace with unnecessary classes and make the class Person more complex than it should be.

PHP access methods from parent class

Hello guys I'm new to PHP's OOP so I need a little help from my test scripts.
This is what I've tried so far:
index.php
<?php
include("shared.php");
?>
<!DOCTYPE html>
<html>
<head>
<title>Car Details</title>
</head>
<body>
<?php
$car1 = new Car("Audi");
echo $car1->showCarDetails();
?>
</body>
</html>
car.php
<?php
class Car extends CarDetails {
public $name;
public $color = "Freaking Sexy White";
public $price = "PHP 4,000,000.00";
public function _construct($name) {
$this->setName($name);
$this->getColor();
$this->getPrice();
}
public function setName($name) {
$this->name = $name;
}
public function setColor($color) {
$this->color = $color;
}
public function setPrice($price) {
$this->price = $price;
}
public function getName() {
return $this->name;
}
public function getColor() {
return $this->color;
}
public function getPrice() {
return $this->price;
}
public function showCarDetails() {
print nl2br("I have an awesome car. Below are the details :)\r\n".
"Brand: " . $this->getName() . "\r\n" .
"Model: " . parent::getModel(). "\r\n" .
"Color: " . $this->getColor() . "\r\n" .
"Price: " . $this->getPrice()
);
}
}
?>
cardetails.php
<?php
class CarDetails {
public $model = "A7 Sportback";
public $engine = "FSI technology";
public function setModel($model) {
$this->model = $model;
}
public function getModel() {
return $this->model;
}
public function setEngine($engine) {
$this->engine;
}
public function getEngine() {
return $this->getEngine;
}
}
?>
shared.php
<?php
function __autoload($className)
{
//echo "We are requesting the " . $className . " class";
if(file_exists($className . ".php"))
{
require_once($className . ".php");
//echo "The " . $className . " has been included";
}
}
?>
I want to access the method from my parent class which is CarDetails.php, getModel() and getEngine(). But I don't know how to do that, and also what I have declared in the constructor of Car.php in my index.php is not found.
The output:
Notice: Object of class Car could not be converted to int in C:\xampp\htdocs\oop\cardetails.php on line 13
I have an awesome car. Below are the details :)
Brand:
Model: 1
Color: Freaking Sexy White
Price: PHP 4,000,000.00
But my intended output should be:
I have an awesome car. Below are the details :)
Brand: Audi
Model: A7 Sportback
Color: Freaking Sexy White
Price: PHP 4,000,000.00
What is the problem in my code? Any ideas? I'd truly appreciate your help. Thanks.
UPDATE:
I can now access the methods from my parent class. But the problem is, I'm not seeing anything that I declared in my constructor.
Brand: __
Where it should be:
Brand: Audi
Since I passed in "Audi" in index.php
You have a couple of typos in cardetails.php:
public function setEngine($engine) {
$this->engine;
}
public function getEngine() {
return $this->getEngine;
}
should instead be
public function setEngine($engine) {
$this->engine = $engine;
}
public function getEngine() {
return $this->engine;
}
Also, in car.php:
public function _construct($name) {
should be
public function __construct($name) {
I believe that's causing the weirdness you're seeing.
So I've made a few changes here, the whole point behind extending your class is so that your child class HAS the public/protected functionality that the parent class had.
This would mean that your child class Car shouldn't need to call parents when accessing the getModel or any other functions.
You can see the code changes run live here, https://ideone.com/vCfxYQ
<?php
class Car extends CarDetails {
public $name;
public $color = "Freaking Sexy White";
public $price = "PHP 4,000,000.00";
public function __construct($name) {
$this->setName($name);
$this->getColor();
$this->getPrice();
}
public function setName($name) {
$this->name = $name;
}
public function setColor($color) {
$this->color = $color;
}
public function setPrice($price) {
$this->price = $price;
}
public function getName() {
return $this->name;
}
public function getColor() {
return $this->color;
}
public function getPrice() {
return $this->price;
}
public function showCarDetails() {
print nl2br("I have an awesome car. Below are the details :)\r\n".
"Brand: " . $this->getName() . "\r\n" .
"Model: " . $this->getModel(). "\r\n" .
"Color: " . $this->getColor() . "\r\n" .
"Price: " . $this->getPrice()
);
}
}
class CarDetails {
public $model = "A7 Sportback";
public $engine = "FSI technology";
public function __construct() {
}
public function setModel($model) {
$this->model = $model;
}
public function getModel() {
return $this->model;
}
public function setEngine($engine) {
$this->engine = $engine;
}
public function getEngine() {
return $this->getEngine;
}
}
$car1 = new Car("Audi");
echo $car1->showCarDetails();

Is it possible to pass arguments to the class and the parent class constructor?

Class a {
public function __construct($a){
$this->age = $a;
}
}
Class b extends a {
public function printInfo(){
echo 'age: ' . $this->age . "\n";
}
}
$var = new b('age');
$var->printInfo();
I understand how this code works, however is it possible to pass arguments to the constructor of the class and parent class?
My attempt below is causing an error
Class a {
public function __construct($a){
$this->age = $a;
}
}
Class b extends a {
public function __construct($name){
$this->name = $name;
}
public function printInfo(){
echo 'name: ' . $this->name . "\n";
echo 'age: ' . $this->age . "\n";
}
}
$var = new b('name', 'age');
$var->printInfo();
?>
Yes, you simply need to use the parent::__construct() method.
Like so:
class a{
/**
* The age of the user
*
* #var integer
*/
protected $age;
function __construct($a){
$this->age = $a;
}
}
class b extends a{
/**
* The name of the user
*
* #var string
*/
protected $name;
function __construct($name,$age){
// Set the name
$this->name = $name;
// Set the age
parent::__construct($age);
}
public function printInfo(){
echo 'name: ' . $this->name . "\n";
echo 'age: ' . $this->age . "\n";
}
}
$var = new b('name','age');
$var->printInfo();
Just make sure the variables are set to public or protected!
You can pass value to the parent constructor but the way you are doing is wrong,
$var = new b('name', 'age');
it is as if the child class accepts two parameters in its constructor but in real it has only one parameter.
You can pass parameter to parent constructor something like this
parent::__construct($var);
So change you class b to this
Class b extends a {
public function __construct($name, $age){
$this->name = $name;
parent::__construct($age);
}
public function printInfo(){
echo 'name: ' . $this->name . "\n";
echo 'age: ' . $this->age . "\n";
}
}
Yes you can pass the argument to the class as well as parent class
Class a {
public function __construct($age){
$this->age = $a;
}
}
Class b extends a {
public function __construct($name,$age){
parent::__construct($age);
$this->name = $name;
}
}
$var = new b('name', 'age');
?>
Just call parent::__construct in the child. for example
class Form extends Tag
{
function __construct()
{
parent::__construct();
// Called second.
}
}
Here is how is should go:
<?php
class a {
private $age;
public function __construct($age){
$this->age = $age;
}
public function getAge()
{
return $this->age;
}
}
class b extends a {
private $name;
public function __construct($age, $name){
parent::__construct($age);
$this->name = $name;
}
public function printInfo(){
echo 'name: ' . $this->name . "\n";
echo 'age: ' . $this->getAge() . "\n";
}
}
$b = new b(20, "Bob");
$b->printInfo();
?>

overloading a parent's method in php5

I am struck at overloading the parent's class methods from an inherited child at level2.
abstract class parent
-> child1 extends parent
-> final class child2 extends child1
I want to overload the methods of parent in child2
abstract class Shape
{
protected $length;
protected $height;
protected $a;
protected $b;
protected $c;
public function getCoordinates($length,$height)
{
$this->length=$length;
$this->height=$height;
}
public function getSides($a,$b,$c)
{
$this->a=$a;
$this->b=$b;
$this->c=$c;
}
abstract public function area();
abstract public function perimeter();
abstract public function display();
}
class rectangle extends Shape
{
public function area()
{
return round(($this->length)*($this->height),2);
}
public function perimeter()
{
return round(2*(($this->a)+($this->b)),2);
}
public function display()
{
echo "area is :". rectangle::area() . "<br>";
echo "perimeter is : ". rectangle::perimeter() ."<br>";
}
}
final class triangle extends rectangle
{
function __call($method_name, $arguments) // this is wrong ........please modify here to call area(),which is in shape class();
{
$accepted_methods = array("getCoordinates","area","perimeter");
}
public function area()
{
return round((($this->length)*($this->height)*($this->width)/2),2);
}
public function perimeter()
{
return round((($this->a)+($this->b)+($this->c)),2);
}
public function getCoordinates($length,$height,$width)
{
$this->length=$length;
$this->height=$height;
$this->width=$width;
}
public function display()
{
echo "area is :". triangle::area() . "<br>";
echo "perimeter is : ". triangle::perimeter() ."<br>";
}
}
$r=new rectangle();
$r->getCoordinates(1,2,4);
$r->getSides(6,2);
$r->display();
$ot = new triangle();
$ot->getCoordinates(1,2,4);
$ot->getSides(6,2,3);
$ot->display();
?>
Thanks in advance
$r->getSides(6,2);
Your abstract class demands three arguments! Plus the function is actually a setter method. You should name it setSides();. Same with getCoordinates().
Update: I think you are confusing inheritance with overloading. Here is an example for overloading with __call. I assume that's not what you are trying to do but what you have in your example. Maybe this will help.
abstract class overloadTestAbstract {
public function printOne($show) {
echo __METHOD__ . ': ' . $show . '<br />';
}
}
class overloadTestOne extends overloadTestAbstract {
public function __call($method,$arguments) {
$methods = array('printOne','printTwo','printThree');
if ( in_array($method,$methods) ) {
echo __METHOD__ . ' :OVERLOAD METHOD: ' . $arguments[0] . '<br />';
} else {
echo 'We are so sorry, but this method is available';
}
}
public function printTwo($show) {
echo __METHOD__ . ': ' . $show . '<br />';
}
}
Then if you do this:
$test = new overloadTestOne();
$test->printOne('Hello World');
$test->printTwo('Goodbye World');
$test->printThree('Hello World, again');
$test->printFour('Goodbye World, again');
you will get this
// print results
'overloadTestAbstract::printOne: Hello World'
'overloadTestOne::printTwo: Goodbye World'
'overloadTestOne::__call :OVERLOAD METHOD: Hello World, again'
'We are so sorry, but this method is available'
Although I have printOne and printTwo in the overload __call as accepted methods they are not used because these methods are already defined, they are handled by the existing methods as expected. On the other hand printThree gets overloaded because the method does not exist. Same with printFour but that method has no intend to print the argument. The array you have defined with the accepted methods doesn't do a thing. It is just an array. You have to assign some task to these methods or return some error like I did.

Categories