Как получить свойство родительского объекта внутри дочернего класса в php?

0

Пожалуйста, обратите внимание, что прошло некоторое время с тех пор, как я попробовал свои силы на php и oop...

Я хочу помочь моему партнеру отслеживать нашу массивную коллекцию Magic: The Gathering. В Magic, как правило, карты выпускаются в блоках расширения. Внутри блока есть три расширения. Первое расширение имеет одно и то же имя, символ и т.д. Как весь блок, они действительно более или менее одинаковы, но я хочу сделать разницу между блоком и расширением в моем коде.

В то же время я хотел бы избежать ввода одной и той же информации дважды при добавлении первого расширения в блок;

$block = new Block('Innistrad', 'isd', '130927');
$exp = $block->addExpansion(new Expansion('Innistrad', 'isd', '130927')); // not DRY!
$firstExp = $block->addExpansion(new Expansion('Innistrad')); // This is more DRY, only name is needed

Все расширения имеют ту же дату вращения, что и блок. Это мне удалось установить в методе addExpansion (Expansion $ exp);

$exp->rotationDate = $this->rotationDate;

Как-то я хотел бы добавить условие в конструктор Expansion, чтобы сравнить имя расширения с именем блока. Если они равны, символ расширения совпадает с символом блока, иначе символ расширения устанавливается в методе конструктора. Я пытался использовать $block = get_parent_class($this); а затем $this->name == $block->name как условие, но (конечно?) это не сработало, как ожидалось, и символ расширения "input" имеет значение null? Вместо символа isd.png ".png".

Notice: Trying to get property of non-object in - on line 178
Expansion Object
(
    [name:protected] => Innistrad
    [symbol:protected] => .png
    [rotationDate] => 130927
)

"Полный" код с классами и комментариями, где я пытался и не смог...

// BLOCK
class Block {
    protected static $imgType = '.png';
    protected $name;
    protected $symbol;

    public function __construct($name, $symbol, $rotationDate) {
        $this->name = $name;
        $this->symbol = $symbol.self::$imgType;
        $this->rotationDate = $rotationDate;
    }

    public function addExpansion(Expansion $exp) {
        $exp->rotationDate = $this->rotationDate;
        return $exp;
    }
}

// EXPANSION
class Expansion extends Block {
    public function __construct($name, $symbol = null) {
        $this->name = $name;
        $block = get_parent_class($this); // this is what I tried, the principle of what I try to achieve
        if ($this->name == $block->name) {
        // if the instantiated child object has the same name as the parent object, "adopt" the parent object properties
            $this->symbol = $block->symbol;
        }
        else {
            $this->symbol = $symbol.parent::$imgType;
        }
    }
}
$block = new Block('Innistrad', 'isd', '130927');
$exp = $block->addExpansion(new Expansion('Innistrad'));
print_r($exp);
Теги:
oop
parent-child

3 ответа

0

Я отвечаю, потому что я думаю, что проблема с решением @DarkBee, но у меня нет достаточной репутации для комментариев, поэтому вместо этого я предложу полное решение (проблема в том, что родительский элемент $this-> всегда будет нулевым конструктор Expansion, потому что setParentBlock не вызывается до завершения).

Я скептически отношусь к тому, что вам нужен класс расширения для расширения класса Block, но я все равно оставил его - он работает так же хорошо (лучше, IMO), если вы прокомментируете "extends Block". Любые вопросы, не стесняйтесь спрашивать.

// BLOCK
class Block {
    protected static $imgType = '.png';
    protected $name;
    protected $symbol;
    protected $expansions = array();

    public function __construct($name, $symbol, $rotationDate) {
        $this->name = $name;
        $this->symbol = $symbol.self::$imgType;
        $this->rotationDate = $rotationDate;
    }

    public function addExpansion($name, $symbol = null) {
        // We only have room for 3 expansions.
        if (count($this->expansions) >= 3) return null;

        // If the expansion to be created and added to this block has the
        // same name as this block, or if no symbol is supplied,
        // then "adopt" this block symbol. 
        $symbol = ($name == $this->name || $symbol === null)
          ? $this->symbol
          : $symbol.self::$imgType;

        $exp = new Expansion($name, $symbol, $this->rotationDate);
        $this->expansions[] = $exp;

        return $exp;
    }
}

// EXPANSION
class Expansion extends Block {
    public function __construct($name, $symbolWithType, $rotationDate) {
        $this->name         = $name;
        $this->symbol       = $symbolWithType;
        $this->rotationDate = $rotationDate;
    }
}

$block = new Block('Innistrad', 'isd', '130927');
$exp = $block->addExpansion('Innistrad');
print_r($exp);
0

Кажется, я случайно решил свою проблему. Вместо того, чтобы указывать условие if в конструкторе Expansion, я помещаю его в метод addExpansion() в классе Block. Это дает желаемый результат "принятых" значений свойств, но я не уверен, что это правильное решение.

// BLOCK
class Block {
    protected static $imgType = '.png';
    protected $name;
    protected $symbol;
    protected $rotationDate;

    public function __construct($name, $symbol, $rotationDate) {
        $this->name = $name;
        $this->symbol = $symbol.self::$imgType;
        $this->rotationDate = $rotationDate;
    }

    public function addExpansion(Expansion $exp) {
        $exp->rotationDate = $this->rotationDate;
        if ($exp->name == $this->name) { // if Expansion name equals Block name
            $exp->symbol = $this->symbol; // use Block symbol as Expansion symbol
        }
        return $exp;
    }
}

// EXPANSION
class Expansion extends Block {
    public function __construct($name, $symbol = null) {
        $this->name = $name;
        $this->symbol = $symbol.parent::$imgType;
    }
}
$block = new Block('Innistrad', 'isd_exp_symbol', '20130927');
$exp = $block->addExpansion(new Expansion('Innistrad'));
print_r($exp);

Возвращает:

Expansion Object
(
    [name:protected] => Innistrad
    [symbol:protected] => isd_exp_symbol.png
    [rotationDate:protected] => 20130927
)
  • 0
    Ты сделал это по-другому. Я советую вам хранить расширения в массиве, чтобы вы могли легче их отслеживать
  • 0
    Спасибо, сделаю. =) Это (очень) упрощенная версия моего кода, чтобы выделить и сосредоточиться на прежней (?) Проблеме.
0

Вы злоупотребляете ребенком - родителем. Если u создает Expansion то есть только один объект, а сам его Expansion. Расширение родительского класса не означает, что instance родителя будет создан, он просто заставляет дочерний класс наследовать всю функциональность родительского класса. Вы должны изменить свой метод addExpansion и построить Expansion для чего-то вроде этого:

public function addExpansion(Expansion $exp) {
    $exp->setParentBlock($this);
    $exp->rotationDate = $this->rotationDate;
    return $exp;
}

class Expansion extends Block {
    private $parent = null;

    public function setParentBlock(Block $b) {
      $this->parent = $b;
    }
    public function __construct($name, $symbol = null) {
        $this->name = $name;
        //create getName() because u can't access protected outside the class
        if ($this->parent != null && $this->name == $parent->getName()) {
        // if the instantiated child object has the same name as the parent object, "adopt" the parent object properties
            $this->symbol = $block->symbol;
        }
        else {
            $this->symbol = $symbol.parent::$imgType;
        }
    }
}
  • 0
    Я подозревал, что что-то не так с моим использованием отношений между родителями и детьми. Я попробовал вышеупомянутое предложение, но так и не получил желаемый результат символа Expansion $ равным символу Block $.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню