【问题标题】:Child Class editing Parent Class Property子类编辑父类属性
【发布时间】:2011-06-16 05:28:34
【问题描述】:

我看过类似的问题,但其中提供的解决方案似乎都没有回答我的问题。

这是我目前的代码(刚刚学习 OOP):

<?php

class page {
    var $ot;
    function begin(){
        $this->ot = '';
    }
    function finish(){
        echo $this->ot;
    }


class forms extends page {
    function __construct($form_action, $form_type){
        $this->ot .= '<form action=' . $form_action . ' method=' . $form_type . ' />';
    }
    function create_input($type, $name){
        $this->ot .= '<input type="' . $type . '" name="' . $name . '" /><br />';   
    }
    function create_submit($value){
        $this->ot .= '<input type="submit" value="' . $value . '" />';
    }
    function __destruct(){
        $this->ot .= '</form>';
    }       
}

class labels extends page {
    function create_label($label){
        $this->ot .= '<label>' . $label . ' </label>';
    }
}

$page = new page();
$page->begin();

$newform = new forms('/class_lib.php', 'GET');
$newlabels = new labels();

$newlabels->create_label('Username:');
$newform->create_input('text', 'username');
$newlabels->create_label('Password:');
$newform->create_input('password', 'password');

$page->finish();

 ?>

由于某种原因,此代码不会向浏览器输出任何内容。但是,如果我更改子类 formslabels 以回显它们的输出而不是将其存储在父变量中,那么代码似乎会变得栩栩如生并按预期工作。

请原谅我的无知,因为我是 OOP 的新手。

谢谢!

【问题讨论】:

    标签: php oop inheritance properties


    【解决方案1】:

    $ot 是一个对象属性。这意味着,page 类或任何子类的每个对象都有自己的“版本”$ot。现在您实例化了一些对象并设置了一些值,但最后,当您调用 $page-&gt;finish(); 时,$page-&gt;ot 无论如何都是空的。

    【讨论】:

      【解决方案2】:

      在 OOP 中,您有类(类型)和类(对象)的实例。 $ot 属性就是你所说的实例变量,它属于你创建的实例(对象),而不是类本身的属性。

      通过使表单成为页面的子类,您可以在类之间获得所谓的“是”关系。这意味着表单将继承页面类的结构。在这种情况下,修改子类对象的属性不会影响超类对象或任何其他对象。

      当您第一次创建页面对象时,该对象具有$ot 属性。当您创建表单类型的对象时,该对象有自己的$ot 属性。

      要了解 OOP 的概念,我建议您阅读一些教程。您可以从阅读这篇维基百科文章的类、实例和继承部分开始:

      http://en.wikipedia.org/wiki/Object-oriented_programming

      【讨论】:

        【解决方案3】:

        对象并没有真正连接。

        您创建了三个新对象,但它们从不相互引用。

        试试这个

        // Create a new form
        $newform = new forms('/class_lib.php', 'GET');
        
        $newform->create_input('text', 'username');
        $newform->create_input('password', 'password');
        
        // Output the form, it can use the finish() method because it extends page    
        $newform->finish();
        

        这将起作用并输出&lt;input&gt; 元素,但您的label 类并未插入$newForm 以执行任何操作,它刚刚创建并且是完全独立的。

        编辑 - 今天晚上很无聊....

        你需要 PHP5 来运行它,它并不完美,但它是一个好的开始!我定义了以下一个称为可渲染的接口和称为元素、输入、标签和表单的类

        // An interface describes the methods that a class must use
        interface renderable
        {
            // Any classes that implement the renderabe interface must define a method called render()
            function render();
        }
        
        // This abstract class can never be created, so you can never do new element(), it implements renderable
        abstract class element implements renderable
        {
            // Set up some variables for all elemnts
            var $attribs = array();
            var $name = "";
            var $type = "";    
        
                // The construct for a element needs a type and a name
            function __construct($type, $name)
            {        
                $this->name = $name;        
                $this->type = $type;            
            }
        
            // Set an attribute for the element
            function setAttribute($name, $value)
            {
                $this->attribs[$name] = $value;
            }
        
            // Get the name of this element
            function getName()
            {
                return $this->name;
            }
        
            // The render function outputs an element
            function render()
            {
                // Output the start of the element eg <input
                echo "<" . $this->type . " ";
        
                // each attribute eg class='blue'
                foreach($this->attribs as $name => $value)
                    echo " " . $name . "='" . $value ."' ";         
        
                // end the element
                echo " />";     
        
                echo "<br />";
            }
        }
        
        // The input element extends element but is not abstract
        class input extends element
        {
            // Nothing is overridden here from the parent class element
        }
        
        // The label element extends element but is not abstract
        class label extends element
        {
            // Define a new var called label, this is special for the label element
            var $label = "";
        
            // Override the contruct for element to only accept a name, this
            // is because the label element type will always be label
            function __construct($name)
            {        
                $this->name = $name;        
                $this->type = "label";            
            }
        
            // Set the label var
            function setLabel($label)
            {
                $this->label = $label;
            }   
        
            // Override the render function, this means that label has its own render function
            // and does not use the function from the abstract class element
            function render()
            {
                    echo "<" . $this->type . " ";
        
                    foreach($this->attribs as $name => $value)
                        echo  " " . $name . "='" . $value ."' ";            
        
                    echo " >";
        
                    //  Here the special label content is displayed
                    echo $this->label;
        
                    echo "</label>";        
            }
        }
        
        // A form extends element
        class form extends element
        {
            // A form has some new vars
            var $elements = array();
            var $labels = array();    
        
            var $action;
            var $method;
        
            // Override the contruct and use name, action and method
            // There are default values for action and method so they are not required
            function __construct($name, $action = "/", $method = "GET")
            {        
                $this->name = $name;        
                $this->type = "form";            
                $this->action = $action;
                $this->method = $method;
            }
        
            // Add a new element to the form along with its label
            function appendElement($element, $label)
            {
                // Add these to an array inside this class
                $this->elements[$element->getName()] = $element;
                $this->labels[$label->getName()] = $label;   
            }
        
            // Override the render function
            function render()
            {
                // Output the form's start along with the method and action
                echo '<' . $this->type. ' ' . 'action="' . $this->action . '" method="' . $this->method . '" />';
        
                // Iterate over the array of elments and render each one
                foreach($this->elements as $name => $ele)
                {
                    // Render the label for the current element
                    $this->labels[$name]->render();
                    // Render the element
                        $ele->render();
                }
        
                // End the form
                echo "</form>";
            }
        }
        
        // Create form with name, action and method
        $form = new form("login", "/login.php", "POST");
        
        
        // Create input username
        $ele = new input("input", "username");
        // Set type
        $ele->setAttribute("type", "text");
        // Set a class
        $ele->setAttribute("class", "blue");
        
        // Create a label for the username long with its content
        $label = new label("username");
        $label->setLabel("Username: ");
        
        // Add the username element and its label
        $form->appendElement($ele, $label);
        
        // Repeat for password
        $ele = new input("input", "password");
        $ele->setAttribute("type", "password");
        
        $label = new label("password");
        $label->setLabel("Password: ");
        
        $form->appendElement($ele, $label);
        
        // Render the form
        $form->render();
        

        【讨论】:

        • 这行得通,但我现在需要在页面末尾执行 $newform->finish() 和 $newlabels->finish() 。此外,由于有两个不同的变量,因此 HTML 不会按照我想要的顺序输出。有什么办法解决这个问题?
        • ^ 这是在您编辑之前。 label 应该是 newform 的子类吗?这仍然会导致单独的 $ot 变量吗?
        【解决方案4】:

        既然您正在学习 OOP,那么是时候了解一下Abstract Classes (PHP Manual)

        抽象类是一种定义了一系列通用函数的骨架类。一个抽象类永远不能被实例化(即,你不能调用new AbstractClass),但可以被其他类extended。这允许我们定义一些通用和可重复的东西,比如 HTML 元素,然后随着时间的推移将其扩展到特定的 HTML 元素。这是该概念的示例实现。

        警告:我并不是说 这个 实现是个好主意;仅用于学习目的!

        首先,一些抽象类来定义这些东西应该如何工作。

        abstract class HTMLWriter
        {
            protected $html = '';
            protected $tagName = null;
            protected $selfClosing = false;
            protected $elements = array();
            protected $attributes = array();
        
            protected $closed = false;
        
            abstract public function __construct();
        
            public function addElement(HTMLWriter $element)
            {
                if ($this->closed || $this->selfClosing) {
                    return;
                }
                $element->close(); // automatic!
        
                $this->elements[] = $element->write();
            }
        
            public function addElements() {
                foreach (func_get_args() as $arg) {
                    if ($arg instanceof HTMLWriter) {
                        $this->addElement($arg);
                    }
                }
            }
        
            public function addAttribute($name, $value)
            {
                return $this->attributes[$name] = $value;
            }
        
            public function write()
            {
                if (!$this->closed) {
                    $this->close();
                }
                return $this->html;
            }
        
            public function close()
            {
                $this->closed = true;
                $this->html = '<' . $this->tagName;
                foreach ($this->attributes AS $attr => $val) {
                    $this->html .= ' ' . $attr . '="' . $val . '"';
                }
                if ($this->selfClosing) {
                    $this->html .= '/>';
                    return;
                }
                $this->html .= '>';
                foreach($this->elements as $elem) {
                    $this->html .= $elem;
                }
                $this->html .= '</' . $this->tagName . '>';
            }
        }
        
        abstract class HTMLWriterWithTextNodes extends HTMLWriter
        {
            //abstract public function __construct();
        
            public function addText($text)
            {
                $this->elements[] = htmlentities($text);
            }
        
            public function addTextRaw($text)
            {
                $this->elements[] = $text;
            }
        }
        

        然后是这些类的具体实现:

        注意:具体类是任何非抽象类,尽管该术语在应用于不是抽象类扩展的类时失去了意义。

        class Form extends HTMLWriter
        {
            public function __construct($action, $method, $can_upload = false)
            {
                $this->tagName = 'form';
                $this->addAttribute('action', $action);
                $this->addAttribute('method', $method);
                if ($can_upload) {
                    $this->addAttribte('enctype','multipart/form-data');
                }
            }
        }
        
        class Input extends HTMLWriter
        {
            public function __construct($type, $name, $id = null)
            {
                $this->tagName = 'input';
                $this->selfClosing = true;
                $this->addAttribute('type', $type);
                $this->addAttribute('name', $name);
                if (!is_null($id)) {
                    $this->addAttribute('id', $id);
                }
            }
        
            // overrides
            public function addElement()
            {
                return false;
            }
        }
        
        class Label extends HTMLWriterWithTextNodes
        {
            public function __construct($labelText = null, $for = null)
            {
                $this->tagName = 'label';
        
                if (!is_null($labelText)) {
                    $this->elements[] = $labelText;
                }
        
                if (!is_null($for)) {
                    $this->addAttribute('for', $for);
                }
            }
        }
        
        class GenericElement extends HTMLWriterWithTextNodes
        {
            public function __construct($tagName, $selfClosing = false)
            {
                if (empty($tagName)) {
                    $this->closed = true;
                    $this->html = '';
                    return;
                }
                $this->tagName = $tagName;
                $this->selfClosing = (bool)$selfClosing;
            }
        }
        

        最后,让我们实例化并使用我们的新类

        $form = new Form('/class_lib.php','get');
        
        $username = new Input('text','username','username');
        $password = new Input('password','password','password');
        $submit = new Input('submit','login');
        $submit->addAttribute('value','login');
        $ulabel = new Label('Username: ', 'username');
        $plabel = new Label('Password: ','password');
        $br = new GenericElement('br',true);
        
        $form->addElements(
            $ulabel,  $username, $br,
            $plabel,  $password, $br,
            $submit
        );
        
        echo $form->write();
        

        输出:

        <form action="/class_lib.php" method="get"><label for="username">Username: </label><input type="text" name="username" id="username"/><br/><label for="password">Password: </label><input type="password" name="password" id="password"/><br/><input type="submit" name="login" value="login"/></form>
        

        抽象类万岁!

        【讨论】:

          猜你喜欢
          • 2010-12-03
          • 1970-01-01
          • 2013-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-02
          相关资源
          最近更新 更多