Различные экземпляры статического класса в PHP - PullRequest
2 голосов
/ 19 апреля 2011

У меня есть этот код:

<?php
class Animal {
    static public $numLegs;

    public static function Walk() {
        return 'Takes a step with ' . self::$numLegs . ' legs.';
    }
}

class Dog extends Animal {
    public static function Init() {
        parent::$numLegs = 4;
    }
}

class Man extends Animal {
    public static function Init() {
        parent::$numLegs = 2;
    }
}

Dog::Init();
Man::Init();

echo 'The dog walks: ' . Dog::Walk(); //The dog walks: Takes a step with 2 legs.
echo 'The man walks: ' . Man::Walk(); //The man walks: Takes a step with 2 legs.
?>

Проблема в том, что переменная Animal :: $ numLegs одинакова для обоих. Я пытался сделать класс Animal не статичным, но он выдает мне эту ошибку:

"Неустранимая ошибка: доступ к необъявленному статическому свойству: Animal :: $ numLegs in ..."

Я понимаю, что статические классы не могут быть созданы, но я хочу иметь разные «копии» Animal :: $ numLegs для каждого из других статических классов (Man и Dog).

Как я могу это сделать?

Спасибо за ваше время.

Ответы [ 3 ]

3 голосов
/ 19 апреля 2011

В других ответах уже упоминалось Late-Static-Binding как решение вашей проблемы, и это действительно ответ, но никто не реализовал его правильно, а некоторые ответы были слишком сложными.

Статическая переменная предназначена для того, чтобы быть доступной для всех экземпляров или статических обращений к классу в прямом направлении.Итак, как вы сказали в своем коде, Man переписывал значение, установленное Dog, потому что ваша статическая переменная была установлена ​​в родительском классе «Animal», и поэтому была доступна для каждого дочернего класса. Каждый дочерний класс имеет доступ и поэтому может перезаписывать в любой точке.

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

Вот ваш код, правильно использующий позднюю статическую привязку.

<?php

class Animal {
    public static function Walk() {
        return 'Takes a step with ' . static::$numLegs . ' legs.'; //the 'static' keyword lets you operate on child classes' static vars
    }
}

class Dog extends Animal {

    static public $numLegs; //dog has its own static var

    public static function Init() {
        self::$numLegs = 4;
    }
}

class Man extends Animal {

    static public $numLegs; //man has its own static var

    public static function Init() {
        self::$numLegs = 2;
    }
}

Dog::Init();
Man::Init();

echo 'The dog walks: ' . Dog::Walk(); //The dog walks: Takes a step with 2 legs.
echo 'The man walks: ' . Man::Walk(); //The man walks: Takes a step with 2 legs.
?>

И результат:

Собака ходит: делает шаг с 4 ногами. Человек идет: делает шаг с 2 ногами.

1 голос
/ 19 апреля 2011

Вы должны использовать наследование классов.Это происходит по причине: сделать ваш кодер лучше и упростить вещи.Вот пример:

<?php
class Animal {
    protected $numLegs;
    protected $name;

    public function __construct()
    {
       $name = 'Animal';
    }

    public function Walk() {
        return 'The ' . $this->name . 'walks: Takes a step with ' . $this->$numLegs . ' legs.';
    }
}

class Dog extends Animal {
    public function __construct() {
        parent::___construct('Dog');
        $this->$numLegs = 4;
    }
}

class Man extends Animal {
    public function __construct() {
        parent::___construct('Man');
        $this->$numLegs = 2;
    }
}

class Turtle extends Animal {
    public function __construct() {
        parent::___construct('Turtle');
        $this->$numLegs = 4;
    }

    public function Walk() {
        return 'The ' . $this->name . 'walks: SLOWLY takes a step with ' . $this->$numLegs . ' legs.';
    }
}

$dog = Dog->Init();
$man = Man->Init();

echo $dog->Walk(); //The dog walks: Takes a step with 2 legs.
echo $man->Walk(); //The man walks: Takes a step with 2 legs.
?>

Редактировать: я также показал, как вы можете использовать этот способ для создания нового класса и изменения текста, выводимого Walk (), без изменения какого-либо другого класса.

1 голос
/ 19 апреля 2011

Предисловие: Вам нужно использовать PHP 5.3+, чтобы мой пример работал. До PHP 5.3 такого рода вещи не были реально возможны. Введение Поздние статические привязки изменило это. :)


Вы можете использовать константы класса для достижения того же желаемого наследования.

<?php

class Animal {
    const NUM_LEGS = 4;

    public static function Walk() {
        return 'The ' . get_called_class() . ', takes a step with ' . static::NUM_LEGS . " legs.\n";
    }
}

class Dog extends Animal {}

class Man extends Animal {
    const NUM_LEGS = 2;
}

class Shark extends Animal {
    const NUM_LEGS = 0;
}

echo Dog::Walk();   // The Dog, takes a step with 4 legs
echo Man::Walk();   // The Man, takes a step with 2 legs
echo Shark::Walk(); // The Shark, takes a step with 0 legs

В качестве альтернативы, если вы не хотите использовать константу, вы все равно можете использовать переменную. :)

<?php

class Animal {
    public static $numLegs = 4;

    public static function Walk() {
        return 'The ' . get_called_class() . ', takes a step with ' . static::$numLegs . " legs.\n";
    }
}

class Dog extends Animal {}

class Man extends Animal {
    public static $numLegs = 2;
}

class Shark extends Animal {
    public static $numLegs = 0;
}

echo Dog::Walk();   // The Dog, takes a step with 4 legs
echo Man::Walk();   // The Man, takes a step with 2 legs
echo Shark::Walk(); // The Shark, takes a step with 0 legs
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...