Редактирование дочернего класса Свойство родительского класса - PullRequest
1 голос
/ 27 января 2011

Я смотрел на подобные вопросы, подобные этим, и ни одно из предлагаемых в них решений, кажется, не отвечает на мой вопрос.

Это код, который я имею до сих пор (просто изучаю ООП):

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

 ?>

По какой-то причине этот код ничего не выводит в браузер.Однако, если я изменю дочерние классы формы и метки , чтобы отобразить их вывод вместо сохранения его в родительской переменной, код, кажется, оживает и работает как задумано.

Извините за невежество, поскольку я новичок в ООП.

Спасибо!

Ответы [ 4 ]

1 голос
/ 27 января 2011

Поскольку вы изучаете ООП, пришло время узнать о Abstract классах (руководство по PHP) !

Абстрактный класс - это своего рода класс-скелет, который определяет серию универсальных функций. Абстрактный класс никогда не может быть создан (т. Е. Вы не можете вызвать 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>

Ура для абстрактных классов!

1 голос
/ 27 января 2011

$ot является объектом-свойством.Это означает, что каждый объект класса page или любого подкласса имеет свою собственную «версию» $ot.Теперь вы создаете несколько объектов и устанавливаете некоторые значения, но в конце, когда вы вызываете $page->finish(); $page->ot, все равно пусто.

1 голос
/ 27 января 2011

В ООП у вас есть классы (типы) и экземпляры классов (объектов). Свойство $ot - это то, что вы называете переменной экземпляра, оно принадлежит созданным вами экземплярам (объектам) и не является свойством самого класса.

Делая формы подклассом страницы, вы получаете то, что вы называете "является" отношением между классами. Это означает, что формы будут наследовать структуру класса страницы. В этом случае изменение свойства объекта подкласса не повлияет на объекты суперкласса или любой другой объект.

При первом создании объекта страницы этот объект имеет свойство $ot. При создании объекта типа формы этот объект имеет собственное свойство $ot.

Чтобы понять концепции ООП, я бы порекомендовал вам прочитать несколько уроков. Вы можете начать с чтения частей Class, Instance и Inheritance этой статьи в Википедии:

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

1 голос
/ 27 января 2011

Объекты на самом деле не связаны.

Вы создаете три новых объекта, но они никогда не ссылаются друг на друга.

Попробуйте это

// 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...