Jump to content

Abstract Classes


Strider64
Go to solution Solved by requinix,

Recommended Posts

I am seriously trying to wrap my head around abstract classes, but the more I try to understand it the more I get confused.  :confused:

 

I've even dug out a book by Larry Ullman to no avail.

 

Here's the example in the book:

 

Shape abstract class

<?php # Script 6.1 - Shape.php
/* This page defines the Shape abstract class.
 * The class contains no attributes.
 * The class contains to abstract methods.
 * - getArea()
 * - getPerimeter()
 */
 
 abstract class Shape {
	 // No Attributes to declare.
	 // No constructor or destructor defined here.
	 
	 // Method to calculate and return the area.
	 abstract protected function getArea();
	 // Method to calculate and return the perimeter.
	 abstract protected function getPerimeter();
	 
 } // End of Shape Class.

Triangle class:

<?php # Script 6.2 - Triangle.php
/* This page defines the Triangle class.
 * The class contains two attributes:
 * - private $_sides (array)
 * - private $_perimeter (number)
 * The class contains three methods.
 * - __construct()
 * - getArea()
 * - getPerimeter()
 */
 
class Triangle extends Shape {
	
	// Declare the attributes:
	private $_sides = array();
	private $_perimeter = NULL;
	
	// Constructor:
	function __construct($s0 = 0, $s1 = 0, $s2 = 0) {
	
		// Store the values in the array:
		$this->_sides[] = $s0;
		$this->_sides[] = $s1;
		$this->_sides[] = $s2;
		
		// Calculate the perimeter:
		$this->_perimeter = array_sum($this->_sides);
		
	} // End of constructor.
	
	// Method to calculate and return the area:
	public function getArea() {
		
		// Calculate and return the area:
		return (SQRT(
		($this->_perimeter/2) *
		(($this->_perimeter/2) - $this->_sides[0]) *
		(($this->_perimeter/2) - $this->_sides[1]) *
		(($this->_perimeter/2) - $this->_sides[2])
		));
		
	} // End of getArea() method.
	
	// Method to return the perimeter:
	public function getPerimeter() {
		return $this->_perimeter;
	} // End of getPerimeter() method.
	
} // End of Triangle Class.

and to execute in finding the area and perimeter of a triangle:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Abstract Class</title>
</head>

<body>
<?php # Script 6.3 - abstract.php
// This page uses the Triangle class - (Script 6.2), which is derived from Shape (Script 6.1)

// load the class definitions:
require('Shape.php');
require('Triangle.php');

// Set the triangle's sides:
$side1 = 5;
$side2 = 10;
$side3 = 13;

// Print a little introduction:
echo "<h2>With sides of $side1, $side2, and $side3...</h2>\n";

// Create a new triangle:
$t = new Triangle($side1, $side2, $side3);

// Print the area.
echo '<p>The area of the triangle is ' . $t->getArea() . '</p>';

// Print the perimeter.
echo '<p>The perimeter of the triangle is ' . $t->getPerimeter() . '</p>';

// Delete the object:
unset($t); 
	
?>
</body>
</html>

What is the point of having an abstract class when it runs fine without it being declared? For example I can take out extends Shape in the Triangle class and it will work just fine?  I don't know if If I will ever understand this concept of abstract and interface classes.... :shrug:

 

Any help in this matter will be greatly appreciated. Thanks John 

 

OK, I fooled around with it some more and took out the include('Shape.php') and it spat an out an error stating it wasn't found. So is an abstract class just forcing a person to adhere to the methods being declared in the abstract class? (I'm probably not explaining this right). 

Edited by Strider64
Link to comment
Share on other sites

  • Solution

Abstract classes are the exact same thing as regular classes but with two differences:

1. You can't instantiate an abstract class (but you can instantiate its non-abstract children).

2. Any non-abstract class that inherits from it has to have abstract methods implemented. That doesn't have to be in the class itself but it does have to happen somewhere.

abstract class Animal {

	// this class doesn't know what type of animal it is
	// child classes are supposed to implement it
	public abstract function getAnimalType();

}
abstract class Cat extends Animal {

	// this class, and any child class, is a cat
	public function getAnimalType() {
		return "Cat";
	}

}

abstract class Dog extends Animal {

	// dogs can bark but not all dogs bark the same way
	public abstract function bark();

	// this class, and any child class, is a dog
	public function getAnimalType() {
		return "Dog";
	}

}
class EnglishDog extends Dog {

	public function bark() {
		echo "Woof";
	}

}

class ItalianDog extends Dog {

	public function bark() {
		echo "Bau";
	}

}

class SpanishDog extends Dog {

	public function bark() {
		echo "Guau";
	}

}

To your code:

 

Every shape:

1. Has area but not all shapes calculate the area the same way. This should be an abstract method in Shape.

2. Has a perimeter but not all shapes calculate the perimeter the same way. This should also be an abstract method in Shape.

 

The Shape class itself should be abstract for two reasons:

1. It has abstract methods so you must make the class abstract. Fortunately that makes sense because...

2. Everything that you would consider a shape is more precisely a type of shape. That means subclass. It doesn't make sense to have an instance of Shape itself.

 

Triangle should extend from Shape (it's a type of shape) and can implement the getArea and getPerimeter methods. You could make subtypes of triangle, like RightAngledTriangle or IsocelesTriangle, and put the code in each of those, but they actually all have the same implementation so it's better to put the code in the parent class (Triangle) instead.

 

 

What is the point of having an abstract class when it runs fine without it being declared? For example I can take out extends Shape in the Triangle class and it will work just fine?  I don't know if If I will ever understand this concept of abstract and interface classes.... :shrug:

OK, I fooled around with it some more and took out the include('Shape.php') and it spat an out an error stating it wasn't found. So is an abstract class just forcing a person to adhere to the methods being declared in the abstract class? (I'm probably not explaining this right).

Abstract classes share some of the power that interfaces have: you can write code that uses Shapes without having to care about what type of shape it is. Without the parent Shape class, if you wanted to deal with Triangles and Squares then you'd have to

a) Write a bunch of methods, one for each type of shape. If you added more shapes in the future then you'd have to add more methods. To call those methods you'd have a bunch of logic somewhere that says "if it's a Triangle then call method A, if it's a Square then call method B, if it's a Circle then call method C..." and that is a nightmare to maintain.

b) Write one method that handles all types of shapes. It's nicer in that you have only the one method, but that method can't use typehinting because the various shapes don't have a parent class in common. So then you'd have to check that the value passed was an appropriate type of shape (with the same kind of "bunch of logic" as above); if you blindly called "->getArea" on whatever you received then anyone could pass any type of object so long as it had a method named "getArea".

 

It's a trivial example but

function whatIsMyArea(Shape $shape) {
	echo "The area of this shape is ", $shape->getArea(), "\n";
}
1. It enforces that every value passed is a Shape (or subclass of Shape).

2. Since you know it's a Shape, you also know that it has a getArea method you can call.

3. More logically, you know that the function was passed an object representing a shape and not, like, a "user" or a "car" or something unexpected.

You can't get that kind of certainty unless you (a) use Shape or (b) write a lot of code.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.