ch06 object oriented features

Posted by himnbandit on Wed, 15 Jan 2020 10:27:27 +0100

Article directory

Object oriented features

Understanding object-oriented concept

Object oriented (OO) development method will introduce object classification, relation and attribute into the system, so as to help program development and code reuse.

Classes and objects

  1. Object oriented software consists of a series of self-contained objects with attributes and operations, which can interact with each other to meet our requirements. An object property is a property or variable related to an object. An operation is a method, behavior, or function that an object can perform to change itself or make an impact on the external world (properties can be used interchangeably with member variables and properties, while operations can be used interchangeably with methods).

  2. An important advantage of object-oriented software is to support and encourage the ability of encapsulation, which is also called data hiding. In essence, access to the data in an object can only be achieved through the operation of the object, which is also the interface of the object. Encapsulation allows you to modify or fix bug s without affecting other parts of the project.

  3. In object-oriented software, an object is a collection of methods that can store and manipulate data. This collection is unique and identifiable. Objects can be classified by class. Class is a collection of objects that represent things that may not be the same as each other, but must have some common ground. Although the objects contained in a class may have different property values, they all have the same operations implemented in the same way and the same properties representing the same transaction.

Polymorphism

The object-oriented programming language must support polymorphism, which means that different kinds of operations can have different behaviors and implementations for the same operation. In PHP, only the member functions of a class can be polymorphic.

inherit

Inheritance allows us to use subclasses to create hierarchical relationships between classes. A subclass inherits properties and operations from its superclass, also known as its parent. By inheritance, we can create new classes based on existing classes. =>Make the code more reusable.

Create classes, properties, and actions

Class structure

-Create a class using the keyword class
 -You can create properties by declaring variables with certain keywords in the class definition. These keywords relate to variable scopes: public, private, protected
 -By declaring a function in a class definition, you can create an operation of the class.
class classname{
    public $attribute1;
    public $attribute2;
    function operation1(){
        //operation
    }
    function operation2($param1, $param2){
        //operation
    }
}

Constructor

When an object is created, its constructor is called. Typically, this performs some effective initialization tasks.

The declaration of a constructor is the same as that of other operations except that its name must be \.

function __construct($param){
    echo "Construct called with parameter".$param."<br />";
}

PHP allows function overloading, which means multiple functions with the same name can be provided, but they must have different numbers or types of parameters.

Destructor

A destructor allows a class to be called before it is destroyed. It performs some operations or functions, which usually occur automatically when all references to the class are reset or out of scope.

The name of the destructor must be 'destruct(). The destructor cannot take any parameters.

Class instantiation

After a class is declared, an object for use is created, which is a specific individual, that is, a member of the class. Create an object using the keyword new. You need to specify which instance of the class to create the object with any required parameters for the constructor.

class classname{
    function __construct($param){
    echo "Construct called with parameter".$param."<br />";
}
}
$a = new classname("First");
$b = new classname("Second");

Use class properties

In a class, you can access a special pointer: this. You can use this. You can use this. Variables can be referenced through this - > attribute.

class classname
{
    public $attribute;
    function operation($param)
    {
        $this->attribute = $param;
        echo $this->attribute;
    }
}

Whether a property can be accessed outside the class is determined by the access modifier.

Call class action

Class operations can be called by methods with the same calling class properties. Class operations can be called by methods of other functions according to Dior: operation name and necessary parameters.

class classname
{
    function operation1()
    {
        //operation
    }
    function operation2($param1, $param2)
    {
        //operation
    }
}
$a = new classname();
$a -> operation1();
$a -> operation2(12,'test');
$x = $a -> operation1(); #If there is a return value, this method obtains the return data

Using private and public keywords to control access

Access modifier: controls the visibility of properties and methods. Typically, access modifiers are placed before property and method declarations.

-public: the default option. public properties or methods can be accessed inside and outside the class.
-Private: the marked property or method can only be accessed directly inside the class. And private properties and methods will not be inherited.
-protected: the marked property or method can only be accessed inside the class. It also exists in any subclass.

Writing accessor functions

In general, it is not a good practice to directly access the class properties outside the class. You can practice the encapsulation feature through the uuu get() and uuu set() functions. In addition to direct access to class properties, if the property is set to private or protected and the accessor function is written, access to all properties can be completed through a piece of code.

class classname
{
    private $attribute;
    function __get($name)  #Return $attribute attribute value
    {
        return $this->$name;
    }
    function __set($name, $value)  #Assign value to attribute $attribute
    {
        $this->$name = $value;
    }
}

- __get()Function: has a parameter (property name) and returns the property value
- __set()Function: has two parameters: property name and value to assign
- These two functions cannot be accessed directly. Double underscores indicate that these functions arePHPHas a special meaning. Use these two functions to check and set the value of any properties that are not directly accessible. Even if these two functions are declared, they will not be used when access is declared as a common property.
$a -> attribute = 5;
#The statement implicitly calls the \\\\\\\\\\\\.

$a -> attribute
#This code will implicitly call the 65123; get() function, where the $name parameter value is set to "attribute", and the code implementation of the return parameter value of ﹣ get() function is provided by the programmer

Advantages of accessor function: you only need to modify the code in one place to achieve all the functions to be modified.

Implementing inheritance in PHP

To specify that one class becomes a subclass of another, use the keyword extends.

class A
{
    public $attribute1;
    function operation1()
    {}
}
class B extends A
{
    public $attribute2;
    function operation2()
    {}
}
#All the following operations and property access to class B objects are effective. As A subclass of A, class B has the same functions and data as A.
$b = new B();
$b -> operation1();
$b -> attribute1 = 10;
$b -> operation2();
$b -> attribute2 = 5;

Inheritance is one-way. A child class can inherit properties from its parent class or from its super accumulation, but a parent class cannot inherit properties from its child class.

Using private and protected to control visibility through inheritance

<?php

class A
{
    private function operation1()
    {
        echo "operation1 called,"."<br />";
    }
    protected function operation2()
    {
        echo "operation2 called."."<br />";
    }
    public function operation3()
    {
        echo "operation3 called."."<br />";
    }
}

class B extends A
{
    function __construct()
    {
        # $this -> operation1();
        # Error: Call to private method A::operation1() from context 'B' 
        $this -> operation2();
        $this -> operation3();
    }
}

$b = new B;
?>

Description: private operation cannot be invoked in subclasses.

# $b -> operation2();
# Error: Call to protected method A::operation2() from context ''
$b -> operation3();

Note: the protected function can be inherited but can only be used inside a subclass.

cover

In subclasses, it is also valid to declare the same properties and actions again, and in some cases this can be useful.

Override: in a subclass, give a property a default value different from its superclass property value, or give an operation a function different from its superclass operation.

<?php

class A
{
    public $attributre = 'default value';
    function operation()
    {
        echo "Something<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
}

class B extends A
{
    public $attributre = 'different value';
    function operation()
    {
        echo "Something else<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
}

$a = new A();
$a -> operation();

$b = new B();
$b -> operation();

?>

Just as defining new properties and operations in a subclass does not affect a superclass, overriding properties or operations in a subclass does not affect a superclass. If the subclass provides an alternative definition, the alternative definition takes precedence and overrides the original definition.

The parent keyword allows the initial version of the parent operation to be called. Although the operation of the parent class is called, PHP will use the property value of the current class.

<?php

class A
{
    public $attributre = 'default value';
    function operation()
    {
        echo "Something<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
}

class B extends A
{
    public $attributre = 'different value';
    function operation()
    {
        parent::operation();  #Use of parent keyword!!!
    }
   
}

$a = new A();
$a -> operation();

$b = new B();
$b -> operation();

?>

Use the final keyword to inherit and overwrite

When the keyword is used before a function declaration, the function can no longer be overridden in any subclass; you can also use the final keyword to prevent a class from being inherited.

class A
{
    public $attributre = 'default value';
    final function operation()
    {
        echo "Something<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
}
class B extends A
{
    public $attributre = 'different value';
    function operation()
    {
        echo "Something else<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
   
}
# Fatal error: Cannot override final method A::operation()
final class A
{
    public $attributre = 'default value';
    final function operation()
    {
        echo "Something<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
}

class B extends A
{
    public $attributre = 'different value';
    function operation()
    {
        echo "Something else<br />";
        echo 'The value of $attributre is '.$this -> attributre.'<br />';
    }
   
}
#Fatal error: Class B may not inherit from final class (A)

multiple inheritance

PHP does not support multiple inheritance. That is, each class can only inherit one parent class, and a parent class can have multiple children.

Multiple inheritance: easy to confuse.

PHP does not support multiple inheritance, but it provides two mechanisms to support multiple inheritance: interface and Trait.

Interface

Interface idea: specifies a series of functions that must be implemented by a class that implements the interface.

interface Displayable
{
    function display(); #Interface does not need to include implementation
}
class webPage implements Displayable  #The webPage class can inherit a class and implement one or more interfaces at the same time
{
    function display()
    {
        //...
    }
}

Trait

In trade, you can group functions that will be reused in multiple classes. A class can combine multiple traits, and Trait can inherit other traits.

It includes implementation; it is the best building block for code reuse.

<?php

    trait logger
    {
        public function logmessage($message, $level = 'DEBUG')
        {
            //wwrite $message to a log
        }
    }
    class fileStorage
    {
        use logger;
        function store($data)
        {
            //...
            $this -> logmessage($msg);
        }
    }
?>

By default, the trail method overrides the inherited method.

One advantage of a trade is that you can combine multiple trades, and when there are multiple methods with the same name, you can explicitly specify the features that you need to use a specific trade.

<?php

    trait fileLogger
    {
        public function logmessage($message, $level = 'DEBUG')
        {
            //wwrite $message to a log
        }
    }
    trait sysLogger
    {
        public function logmessage($message, $level = 'ERROR')
        {
            //write $message to the syslog
        }
    }
    class fileStorage
    {
        use fileLogger, sysLogger
        {
            fileLogger::logmessage insteadOf sysLogger;   #Instead of keyword: Specifies the trail to use
            sysLogger::logmessage as private logsysmessage;  #as keyword: Rename trail
        }
        function store($data)
        {
            //...
            $this -> logmessage($message);
            $this -> logsysmessage($message);
        }
    }
?>

Horizontal composition: a Trait that is completely composed of or contained in other traits, using the use statement within a Trait just as it is used in a class.

Class design

Create class: reduce the HTML code required to create a new page. In this way, when you modify a page, you only need to modify different parts of the page, and the same parts will be generated automatically. This type should provide a flexible framework for building new pages without restricting the freedom of creation.

Custom class code

Class needs a logical name, meaningful!!!

<?php
    class Page
    {
        //class Page's attributes
        public $content;
        public $title = "TLA Consulting Pty Ltd";
        public $keywords = "TLA Consulting, Three Letter Abbreviation,
                            some of my best friends are search engines";
        public $buttons = array("Home" => "home.php",
                                "Contact" => "contact.php",
                                "Services" => "services.php",
                                "Site Map" => "map.php");
        
        // class Page's operations
        public function __set($name, $value)
        {
            $this -> $name = $value;
        }
        public function Display()
        {
            echo "<html>\n<head>\n";
            $this -> DisplayTitle();
            $this -> DisplayKeywords();
            $this -> DisplayStyles();
            echo "</head>\n<body>\n";
            $this -> DisplayHeader();
            $this -> DisplayMenu($this -> buttons);
            echo $this -> content;
            $this -> DisplayFooter();
            echo "</body>\n</html>\n";
        }
        public function DisplayTitle()
        {
            echo "<title>".$this -> title."</title>";
        }
        public function DisplayKeywords()
        {
            echo "<meta name = 'keywords' content='".$this -> keywords."'/>";
        }
        public function DisplayStyles()
        {
            ?>
            <link href="styles.css" type="text/css" rel="stylesheet">
            <?php
        }
        public function DisplayHeader()
        {
            ?>   
            <!-- page header -->
            <header>    
            <img src="logo.gif" alt="TLA logo" height="70" width="70" /> 
            <h1>TLA Consulting</h1>
            </header>
            <?php
        }
        public function DisplayMenu($buttons)
        {
            echo "<!-- menu -->
            <nav>";

            foreach($buttons as $name => $url){
            #while (list($name, $url) = each($buttons)) {
            $this->DisplayButton($name, $url, 
                    !$this->IsURLCurrentPage($url));
            }
            echo "</nav>\n";
        }
        public function IsURLCurrentPage($url)
        {
            if (strpos($_SERVER['PHP_SELF'],$url) === false)
            {
                return false;
            }else{
                return true;
            }
        }
        public function DisplayButton($name,$url,$active=true)
        {
            if ($active) { ?>
            <div class="menuitem">
                <a href="<?=$url?>">
                <img src="s-logo.gif" alt="" height="20" width="20" />
                <span class="menutext"><?=$name?></span>
                </a>
            </div>
            <?php
            } else { ?>
            <div class="menuitem">
            <img src="side-logo.gif">
            <span class="menutext"><?=$name?></span>
            </div>
            <?php
            }  
        }

        public function DisplayFooter()
        {
            ?>
            <!-- page footer -->
            <footer>
            <p>&copy; TLA Consulting Pty Ltd.<br />
            Please see our 
            <a href="legal.php">legal information page</a>.</p>
            </footer>
            <?php
        }
    }
?>

The homepage uses Page class to complete most of the work of generating Page content

<?php
    require("page.php");

    $homepage = new Page();

    $homepage->content ="<!-- page content -->
                       <section>
                       <h2>Welcome to the home of TLA Consulting.</h2>
                       <p>Please take some time to get to know us.</p>
                       <p>We specialize in serving your business needs
                       and hope to hear from you soon.</p>
                       </section>";

    $homepage -> Display();
?>

A better way is to use inheritance to create a new class. The new class inherits most functions from the Page class, but covers the parts that need to be modified.

<?php
  require ("page.php");

  class ServicesPage extends Page
  {
    private $row2buttons = array(
                           "Re-engineering" => "reengineering.php",
                           "Standards Compliance" => "standards.php",
                           "Buzzword Compliance" => "buzzword.php",
                           "Mission Statements" => "mission.php"
                           );

    public function Display()
    {
      echo "<html>\n<head>\n";
      $this->DisplayTitle();
      $this->DisplayKeywords();
      $this->DisplayStyles();
      echo "</head>\n<body>\n";
      $this->DisplayHeader();
      $this->DisplayMenu($this->buttons);
      $this->DisplayMenu($this->row2buttons);
      echo $this->content;
      $this->DisplayFooter();
      echo "</body>\n</html>\n";
    }
  }

  $services = new ServicesPage();

  $services -> content ="<p>At TLA Consulting, we offer a number
  of services.  Perhaps the productivity of your employees would
  improve if we re-engineered your business. Maybe all your business
  needs is a fresh mission statement, or a new batch of
  buzzwords.</p>";

  $services->Display();
?>

Advanced object-oriented functions

Use class level constants

Class level constant: used without initializing the class. Class level constant is accessed by:: operator and specifying the class to which the constant belongs.

<?php
    class Math{
    const pi = 3.14159;
}
echo "Math::pi = ".Math::pi;
?>

Implementing static methods

Static keyword: used to allow methods to be called without class initialization. this keyword cannot be used in a static method.

<?php
    class Math{
    static function squared($input)
    {
        return $input*$input;
    }
}
echo Math::squared(8);
?>

Check class type and type prompt

The instanceof keyword allows you to check the type of an object. It can check whether an object is an instance of a specific class, whether it inherits from a class or implements an interface. The iinstanceof keyword is an efficient conditional operator.

In the previous example, class B is a subclass of class A
 {$b instanceof B} returns true
 {$b instanceof A} returns true
 {$b instanceof Displayable} returns false

PHP also provides the function of type prompt. Using the type prompt, you can specify the type of parameter class that must be passed in. At the same time, if the type of parameter class passed in is not the specified type, an error will occur. Type hints apply to classes and interfaces, not to traits.

function check_hint(B $someclass){
    //...
}
The above example requires that $someclass must be an instance of class B. If an instance of another class is passed in, an error will occur.

Delay static binding

In an inheritance level where the same function is implemented by multiple implementations, you can use delayed static binding to determine the method that calls a specific class.

<?php
    class A
    {
        public static function whichclass()
        {
            echo __CLASS__;
            echo "<br />";
        }
        public static function test()
        {
            self::whichclass();
        }
    }
    class B extends A
    {
        public static function whichclass()
        {
            echo __CLASS__;
        }
    }

    A::test();
    B::test();
?>

In the above code, although class B overrides which class() method, when B calls the test() method, the test() method will execute in the context of parent class A. Use delayed static binding to solve this problem.

static::whichclass();   #The static modifier ensures that PHP uses classes that are called at run time

Object cloning

clone keyword: allows copying an existing object.

$c = clone $b;
#A copy of $b will be created with the same type and property value as $b.

If you get non default behavior by cloning, you must create a \\\\\\\\. This method is similar to a constructor or destructor and will not be called directly. One advantage of this method is that it can be called after creating a copy of the default behavior using the default behavior. At this stage, change only what needs to be changed.

Using abstract classes

Abstract class: can't be instantiated. The same class method has no implementation. It only provides the declaration of class method, without specific implementation.

Any class containing abstract methods must be abstract in itself. You can also declare an abstract class without any abstract methods.

Abstract methods and abstract classes are mainly used in complex class hierarchy, which needs to ensure that each subclass contains and covers some specific methods, which can also be realized through interfaces.

__call() overload method

__call() function: to implement method overloading, the method must have two parameters, the first contains the name of the called method, and the second contains the array of parameters passed to the method.

public function __call($method, $p)
{
    if($method == 'display'){
        if(is_object($p[0])){
             $this -> displayObject($p[0]);
        }else if(is_array($p[0])){
            $this -> displayArray($p[0]);
        }else{
            $this -> displayScalar($p[0]);
        }
    }
}

__autoload() method

This function is a separate function that can be declared outside of any declaration. If this function is implemented, it will be called automatically when an undeclared class is instantiated. The main purpose of this method is to try to introduce a specific file that is needed to initialize the required classes.

function __autoload($name){
    include_once $name.".php";  #Introduce a file with the same name as the class
}

Iterators and iterations

To implement an Iterator, the iterated class must implement the IteratorAggregate interface, and define a getIterator method that can return an instance of the iterated class. This class must implement the Iterator interface, which provides a series of methods that must be implemented.

<?php
class ObjectIterator implements Iterator {

   private $obj;
   private $count;
   private $currentIndex;

   function __construct($obj)  #The constructor is not required, but it is obvious that you can set the number of items to be iterated and the link to the current data item in the constructor
   {
     $this->obj = $obj;
     $this->count = count($this->obj->data);
   }
   function rewind() #Set the internal data pointer to the beginning of the data
   {
     $this->currentIndex = 0;
   }
   function valid()  #Will judge whether there is more data in the current position of data pointer
   {
     return $this->currentIndex < $this->count;
   }
   function key() #Return data pointer value
   {
     return $this->currentIndex;
   }
   function current()  #The value saved in the current data pointer
   {
     return $this->obj->data[$this->currentIndex];
   }
   function next()  #Move data pointer position in data
   {
     $this->currentIndex++;
   }
}

class Object1 implements IteratorAggregate
{
  public $data = array();

  function __construct($in)
  {
    $this->data = $in;
  }

  function getIterator()
  {
    return new ObjectIterator($this);
  }
}

$myObject = new Object1(array(2, 4, 6, 8, 10));

$myIterator = $myObject->getIterator();
for($myIterator->rewind(); $myIterator->valid(); $myIterator->next())
{
  $key = $myIterator->key();
  $value = $myIterator->current();
  echo $key." => ".$value."<br />";
}

?>

generator

The generator is understood as: define time like function, run-time to iterator.

The generator needs to use the yield keyword to return the execution result.

The generator function must be invoked in the foreach loop, which creates a Generator object that can preserve the internal state of the generator function. In each iteration of the external foreach loop, the generator performs the next internal iteration.

In the next iteration of the external foreach loop, the generator continues from where it last ended until the next yield statement is encountered.

<?php

function fizzbuzz($start, $end)
{
  $current = $start;
  while ($current <= $end) {
    if ($current%3 == 0 && $current%5 == 0) {
      yield "fizzbuzz";
    } else if ($current%3 == 0) {
      yield "fizz";
    } else if ($current%5 == 0) {
      yield "buzz";
    } else {
      yield $current;
    }
    $current++;
  }
}

foreach(fizzbuzz(1,20) as $number) {
  echo $number.'<br />';
}
?>


Iterator uses lazy execution, only one value at a time will be created and saved in memory!!!

Convert class to string

__toString() function: all the returned contents of this function will be printed by the echo statement.

<?php
   class Printable
   {
       public $testone;
       public $testtwo;
       public function __toString()
       {
           return (var_export($this, TRUE));
       }
   }
?>

Using the reflection API

Reflection: the ability to find the structure and content of classes and objects by accessing existing classes and objects.

#reflection.php
<?php
    require_once("page.php");

    $class = new ReflectionClass("Page");
    echo "<pre>".$class."</pre>";  #< pre > tags on different lines
?>

Namespace

Namespace: a method for classifying a set of classes and / or functions. It can aggregate related content into a function library.

Benefits: avoid name conflicts; helps shorten class names.

Create: specific namespace value after the keyword namespace. In the file, the code after the namespace declaration will automatically do the namespace. Note that if you need to declare a namespace in a file, the first line of the file must be a namespace declaration.

#orders.php
<?php
    namespace orders;
    class order
    {
        //...
    }
    class orderItem
    {
        //...
    }
?>
#Access these classes -- prefixed
include 'orders.php';
$myOrder = new orders\order();
## Without prefix
namespace orders;  #The namespace declaration is at the head of the file, so you do not need to add a prefix
include 'orders.php';
$myOrder = new order();

Please note: when using the functions of the orders namespace, you need to use the specific value of the namespace as the prefix, plus the backslash \, and then the class name to be used. Backslash \ is the namespace separator.

For any class referenced within a namespace, if a full namespace is not specified, it is considered in the current namespace. However, PHP will search for functions and constants in the current namespace that do not have full names, and if they are not found, PHP will search in the global namespace. This behavior i does not apply to classes.

Subnamespace

Namespaces also have hierarchies

<?php
    namespace bob\html\page;
    class Page{
        //...
    }
?>
# Using the Page class outside the namespace
$services = new bob\html\page\Page();
# Using the Page class in the bob namespace
$services1 = new html\page\Page();

Global namespace

Any code that is not written under a declared namespace is considered a global namespace.

There is a global namespace class Page. If you want to access,
$services2 = \Page();

Namespace import and aliases

use statements can be used as imports and aliases for namespaces

#Code using bob\html\page namespace
use bob\html\page;
$services3 = new page\Page();

#Use as to define aliases
use bob\html\page as www;
$services4 = new www\Page();
Published 11 original articles, praised 0, visited 115
Private letter follow

Topics: PHP Attribute Programming