Инициализация класса с неправильным вводом делает его непригодным для использования, но объект все еще существует - PullRequest
2 голосов
/ 27 октября 2010

Если я хочу создать новый объект, который нуждается в определенной информации, такой как идентификатор продукта или что-то в этом роде, но ввод плохой, как я могу элегантно управлять таким делом?таким образом я все еще получаю объект (так как return внутри конструктора ничего не возвращает).Другим способом было бы использовать исключения, которые я мог бы затем отловить, но это довольно нелегко.Третий вариант - использовать статическую функцию, которая затем проверяет ввод и затем возвращает объект.

class Product
{
static function init($id)
    {
    if(is_invalid_id($id))
        { return false; }
    return new self($id);
    }

private function __construct($id)
    {
    $this->id = $id;
    }
}

$product = Product::init($productId);

Проблема здесь в том, когда я пытаюсь расширить класс.Либо мне нужно создать init() метод для каждого расширяемого класса (даже если это точно такой же код), либо return new self() всегда возвращает экземпляр родительского класса.

Ответы [ 4 ]

3 голосов
/ 27 октября 2010

Бросить исключение . Не уверен, почему вы считаете это нелегальным. Чувак, все было нелегко до исключений (ЛОЖЬ, -1, ноль)

1 голос
/ 27 октября 2010

Для проблемы с self:: вы можете использовать позднюю статическую привязку (PHP5.3 +):

<?php

class Product
{
static function init($id)
    {
    if(false)
        { return false; }
    $s = get_called_class();
    return new $s($id);
    }

private function __construct($id)
    {
    $this->id = $id;
    }
function getId()
    {
    return "Product-$this->id";
    }
}


class Headphones extends Product
{
function getId()
    {
    return "Headphones-$this->id";
    }
}

$c1 = Product::init(1);
$c2 = Headphones::init(1);
printf("c1 is %s, c2 is %s\n", $c1->getId(), $c2->getId());
// Prints: c1 is Product-1, c2 is Headphones-1
?>
1 голос
/ 27 октября 2010

Ваш третий вариант - Заводской шаблон .

Как вы заметили, недостатком является то, что каждому классу, который нуждается в такой проверке, обычно нужен свой собственный метод фабрики.

0 голосов
/ 27 октября 2010

Я дам вам нестандартный обходной путь, на который повсеместно смотрят пуристы: гибридный конструктор

И это даже больше зла, чем кажется, потому что на самом деле это просто процедура-обертка:

function Product($i) {
    $prod = new Product($i);
    return $prod->valid() ? $prod : new InvalidProduct();
}

class Product {
    function __construct() { ... }
}
class InvalidProduct extends Product implements Stub { }


$new_prod = Product("oops123");   // what will it be?

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

И есть второй вариант: просто залог за исключением.

...