abstracting classes

I do not understand
what difference is
$address_residence->address_type_id = 1;
and regular address types (street address, city_name, subdivision_name)

If parent class is declared abstract, am I forced to use the child classes (new AddressBussiness, new AddressResidence, new AddressPark) in demo.php and not the parent class (new Address)

and could you explain this tutorial

from Lynda.com object oriented php tutorial
abstracting classes


 * Physical address. 
abstract class Address {
  const ADDRESS_TYPE_PARK = 3;
  // Address types.
  static public $valid_address_types = array(
    Address::ADDRESS_TYPE_RESIDENCE => 'Residence',
    Address::ADDRESS_TYPE_BUSINESS => 'Business',
    Address::ADDRESS_TYPE_PARK => 'Park',
  // Street address.
  public $street_address_1;
  public $street_address_2;
  // Name of the City.
  public $city_name;
  // Name of the subdivison.
  public $subdivision_name;
  // Postal code.
  protected $_postal_code;
  // Name of the Country.
  public $country_name;
  // Primary key of an Address.
  protected $_address_id;
  // Address type id.
  protected $_address_type_id;
  // When the record was created and last updated.
  protected $_time_created;
  protected $_time_updated;
   * Constructor.
   * @param array $data Optional array of property names and values.
  function __construct($data = array()) {
    $this->_time_created = time();
    // Ensure that the Address can be populated.
    if (!is_array($data)) {
      trigger_error('Unable to construct address with a ' . get_class($name));
    // If there is at least one value, populate the Address with it.
    if (count($data) > 0) {
      foreach ($data as $name => $value) {
        // Special case for protected properties.
        if (in_array($name, array(
        ))) {
          $name = '_' . $name;
        $this->$name = $value;
   * Magic __get.
   * @param string $name 
   * @return mixed
  function __get($name) {
    // Postal code lookup if unset.
    if (!$this->_postal_code) {
      $this->_postal_code = $this->_postal_code_guess();
    // Attempt to return a protected property by name.
    $protected_property_name = '_' . $name;
    if (property_exists($this, $protected_property_name)) {
      return $this->$protected_property_name;
    // Unable to access property; trigger error.
    trigger_error('Undefined property via __get: ' . $name);
    return NULL;
   * Magic __set.
   * @param string $name
   * @param mixed $value 
  function __set($name, $value) {
   /* // Only set valid address type id.
    if ('address_type_id' == $name) {
    // Allow anything to set the postal code.
    if ('postal_code' == $name) {
      $this->$name = $value;
    // Unable to access property; trigger error.
    trigger_error('Undefined or unallowed property via __set(): ' . $name);
   * Magic __toString.
   * @return string 
  function __toString() {
    return $this->display();
  * force extending classes to implement init method
  abstract protected function _init();
   * Guess the postal code given the subdivision and city name.
   * @todo Replace with a database lookup.
   * @return string 
  protected function _postal_code_guess() {
    $db = Database::getInstance();
    $mysqli = $db->getConnection();
    $sql_query  = 'SELECT postal_code ';
    $sql_query .= 'FROM location ';
    $city_name = $mysqli->real_escape_string($this->city_name);
    $sql_query .= 'WHERE city_name = "' . $city_name . '" ';
    $subdivision_name = $mysqli->real_escape_string($this->subdivision_name);
    $sql_query .= 'AND subdivision_name = "' . $subdivision_name . '" ';
    $result = $mysqli->query($sql_query);
    if ($row = $result->fetch_assoc()) {
      return $row['postal_code'];
   * Display an address in HTML.
   * @return string 
  function display() {
    $output = '';
    // Street address.
    $output .= $this->street_address_1;
    if ($this->street_address_2) {
      $output .= '<br/>' . $this->street_address_2;
    // City, Subdivision Postal.
    $output .= '<br/>';
    $output .= $this->city_name . ', ' . $this->subdivision_name;
    $output .= ' ' . $this->postal_code;
    // Country.
    $output .= '<br/>';
    $output .= $this->country_name;
    return $output;
   * Determine if an address type is valid.
   * @param int $address_type_id
   * @return boolean
  static public function isValidAddressTypeId($address_type_id) {
    return array_key_exists($address_type_id, self::$valid_address_types);
   * If valid, set the address type id.
   * @param int $address_type_id 
  protected function _setAddressTypeId($address_type_id) {
    if (self::isValidAddressTypeId($address_type_id)) {
      $this->_address_type_id = $address_type_id;

Open in new window

* define autoloader
* @param string $class_name
function __autoload($class_name){
  include 'class.' .$class_name. '.inc';

echo '<h2>Instantiating AddressResidence()</h2>';
$address_residence = new AddressResidence();

echo '<h2>Setting properties...</h2>';
$address_residence->street_address_1 = '555 Fake Street';
$address_residence->city_name = 'Townsville';
$address_residence->subdivision_name = 'State';
$address_residence->country_name = 'United States of America';
$address_residence->address_type_id = 1;
echo $address_residence;
echo '<pre>';
echo '</pre>';

echo '<h2>Testing AddressBusiness __construct with an array</h2>';
$address_business = new AddressBusiness(array(
  'street_address_1' => '123 Phony Ave',
  'city_name' => 'Villageland',
  'subdivision_name' => 'Region',
  'country_name' => 'Canada',
echo $address_business;
echo '<pre>';
echo '</pre>';

Open in new window

00:00	Visibility scope is not the only object-oriented way to restrict access.
00:04	PHP5 also introduced the concept of abstract classes and methods.
00:09	If a class is defined as abstract, it cannot be instantiated.
00:14	If you define a method as abstract, then any class that extends that
00:18	abstract class containing the method must also declare a method with the
00:22	same name and arguments.
00:24	Further, if a class has an abstract method, then the class itself must be abstract.
00:30	This solves the problem of the generic address class, and provides a mechanism to
00:34	specify the behavior of any child classes.
00:38	Open the address class, scroll to the top, and add the word "abstract" at the
00:43	beginning of the class declaration.
00:45	Save the address, then switch to your browser, and refresh the demo.
00:50	At the bottom, the attempted instantiation of the generic address class has been
00:54	disallowed, and caused a fatal error.
00:56	This is a good thing, as it forces the developer to be specific.
01:00	Edit the demo, and re-factor the second address instance to be a business address,
01:04	including the variable name. AddressBusiness. address_business for the variable
01:13	name as well. And then, add a var_ export at the end, so we can inspect the
01:22	contents. Save the demo, go back to the browser, and refresh.
01:28	The business address is now displayed correctly.
01:31	However, there is a data inconsistency; it's the correct class (AddressBusiness),
01:36	but the _address_type_id is not set.
01:40	Missing property values is a common development problem.
01:43	When working with multiple similar objects, there can be a lot of easily
01:47	forgotten details to keep track of.
01:49	The solution is to initialize objects automatically, so you don't have to
01:53	remember to do it, but what's the best way to initialize them?
01:57	Your first reaction may be to make the construct magic method abstract. This
02:01	would technically work, but you'd end up with a lot of copied and pasted code, as
02:06	everything in construct would have to be duplicated.
02:09	This can easily lead to a fragile system, where re-factoring or adding new
02:13	functionality becomes cumbersome.
02:15	It's not a best practice, and not very object-oriented.
02:19	Instead, I'm going to construct the object in the parent, then call an
02:22	abstract initializer.
02:24	This way, common behavior in the parent's construct method always executes upon
02:28	instantiation. Then, custom behavior can be put in each child's
02:32	initialization method. Neat!
02:35	With these relationships, visibility is also a factor, and abstract method
02:39	visibility can be a bit tricky.
02:41	Methods that implement an abstract method will also need to have the same scope,
02:46	or something a little bit less restrictive.
02:48	If an abstract method is declared as public, I won't be able to change it to private.
02:53	However, the opposite is true.
02:56	I can make an abstract private method public.
02:59	It's a one-way change.
03:01	You can relax the scope restriction, but not make it stricter.
03:05	This prevents a situation when you're expecting to be able to do something, but
03:08	for some strange reason, you are prevented by scope.
03:11	To practically apply this to the addresses, I'm going to require that extending
03:15	classes set the address type id upon creation.
03:19	Let's open the Address class.
03:21	After the magic method toString, define a new abstract protected method called
03:27	init, abstract protected function _init().
03:36	Force extending classes to implement init method, then add a call to the
03:44	initialization method at the beginning of the constructor. $this->init. Save the
03:53	address class, then go to your browser, and refresh.
03:58	You will see an immediate error.
03:59	The AddressResidence class contains an abstract method that needs to be defined.
04:04	So, open the AddressResidence class, and declare the private function initialized.
04:09	protected function _init(). Set the address type id to the constant from the
04:15	address class, using your validating method:
04:18	$this-> setAddressTypeIDAddress::ADDRESS_TYPE_RESIDENCE.
04:27	Add some documentation, and copy the contents of this method, and paste it into
04:39	the business address. ADDRESS_TYPE_ BUSINESS. And, again for the Park. Save, then
04:52	return to your browser, and refresh.
04:55	You'll see that the _address_type_id for the business is now set correctly.
04:59	However, a redundancy has now been introduced with the potential for corruption.
05:04	You can still set the _address_type_ id manually, and if you look at the demo,
05:08	AddressResidence is doing just that.
05:12	You can just remove the _address_type_id, but that treats the symptom, not the problem.
05:16	Return to the address class, and navigate to the magic set method.
05:20	Remove the special case for _address_ type_id. Save, then refresh the demo.
05:28	You will see a notice for undefined or unallowed property.
05:31	Data corruption is now prevented.
05:33	Edit the demo, and remove the now- broken attempt to set the _address_type_id.
05:39	Then save, and refresh.
05:43	The notice is now gone, and execution is error-free.
05:47	In the next segment, I'm going to demonstrate how to implement a common
05:50	interface across all these child address classes without having to know what
05:54	kind of an address type it is.

Open in new window

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
See http://www.php.net/manual/en/language.oop5.abstract.php#82111

Abstract classes share some characteristics with interfaces in that they both produce a "contract" between the programmers working on the project.

An interface tells what methods must be implemented in the class that implements the interface, but it does not have any methods of its own.

An abstract class may have some methods that are fully implemented in the class definition, and may have some methods that are abstract, meaning that they must be defined in the class that extends the abstract class.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rgb192Author Commented:
thank you for abstract and interface definition.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.