子类编辑父类属性

时间:2011-01-26 23:24:38

标签: php oop inheritance properties

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

这是我到目前为止的代码(只是学习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();

 ?>

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

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

谢谢!

4 个答案:

答案 0 :(得分:1)

对象并未真正连接。

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

试试这个

// 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();

这将工作并输出<input>元素,但您的label类未插入$newForm来执行任何操作,它刚刚创建并完全独立。

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

你需要PHP5来运行它,它并不完美,但它是一个好的开始!我已经定义了以下一个名为renderable的接口和名为element,input,label和form的类

// 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();

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

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

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

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

答案 3 :(得分:1)

由于您正在学习OOP,现在是时候了解Abstract Classes (PHP Manual)

抽象类是一种定义一系列泛型函数的骨架类。抽象类永远不能被实例化(即,您不能调用new AbstractClass),但可以被其他类extend编辑。这允许我们定义一些通用且可重复的东西,例如和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>

抽象类的万岁!