(Этот вопрос использует PHP в качестве контекста, но не ограничивается PHP только. например, Любой язык с созданным в хеше также релевантен),
Давайте посмотрим на этот пример (PHP):
function makeAFredUsingAssoc()
{
return array(
'id'=>1337,
'height'=>137,
'name'=>"Green Fred");
}
По сравнению с:
class Fred
{
public $id;
public $height;
public $name;
public function __construct($id, $height, $name)
{
$this->id = $id;
$this->height = $height;
$this->name = $name;
}
}
function makeAFredUsingValueObject()
{
return new Fred(1337, 137, "Green Fred");
}
Метод № 1 является, конечно, более кратким, однако он может легко привести к ошибке такой как
$myFred = makeAFredUsingAssoc();
return $myFred['naem']; // notice teh typo here
Конечно, можно было бы обсудить это $myFred->naem
одинаково приведет к погрешности, которая истинна. Однако наличие формального класса просто чувствует себя более твердым мне, но я не могу действительно выровнять по ширине его.
Каковы были бы профессионалы/недостатки к использованию каждого подхода и когда люди должны использовать который подход?
Под поверхностью два подхода эквивалентны. Тем не менее, вы получаете большую часть стандартных преимуществ OO при использовании класса: инкапсуляция, наследование и т. Д.
Кроме того, посмотрите на следующие примеры:
$arr['naem'] = 'John';
совершенно действует и может быть сложной ошибкой для поиска.
С другой стороны,
$class->setNaem('John');
никогда не будет работать.
Позволить мне поставить этот вопрос вам:
, Что является настолько особенным в создании опечатки как $myFred ['naem']
и создании опечатки как $myFred-> naem
? Та же проблема все еще существует в обоих случаях и они оба ошибка.
мне нравится использовать KISS (сохраните его простым, глупым), когда я программирую.
класс Fred
, т.е. государственная функция acceptsClass ($fredObj Fred)
, Вы, возможно, создали так же легко стандартный класс в противоположность массиву, если это должно использоваться как возвращаемое значение. В этом случае вы могли заботиться меньше о строгом вводе.
$class = new stdClass();
$class->param = 'value';
$class->param2 = 'value2';
return $class;
Я сделал некоторые игры и, наконец, придумал использование overLIB , смотрите мой блог для получения полной информации
-121--4482084-Я предпочитаю иметь жестко закодированные свойства, как во втором примере. Я чувствую, что он более четко определяет ожидаемую структуру класса (и все возможные свойства класса). В отличие от первого примера, который сводится к тому, чтобы просто всегда помнить использовать одни и те же имена ключей. Со вторым можно всегда вернуться и посмотреть на класс, чтобы получить представление о свойствах, просто посмотрев в верхней части файла.
Вам лучше знать, что вы делаете что-то не так со вторым - если вы попытаетесь echo $ this- > donnt Exist
, вы получите ошибку, в то время как если вы попытаетесь echo массив ['donnntExist']
вы не будете.
Если возвращаемое значение представляет сущность в приложении, следует использовать объект, так как это назначение ООП. Если вы просто хотите вернуть группу несвязанных значений, то это не так ясно вырезать. Однако, если это часть открытого API, то объявленный класс по-прежнему является лучшим способом.
Я предпочитаю жестко закодированные свойства, как во втором примере. Мне кажется, что это более четко определяет ожидаемую структуру класса (и все возможные свойства класса). В отличие от первого примера, который сводится к тому, чтобы всегда помнить об использовании одних и тех же имен ключей. Со вторым вы всегда можете вернуться назад и посмотреть на класс, чтобы получить представление о свойствах, просто посмотрев на верхнюю часть файла.
Вам лучше знать, что вы делаете что-то не так со вторым - если вы попробуете echo $this->doesntExist
вы получите ошибку, а если вы попробуете echo array['doesntExist']
вы не получите.
Для простых представленных чехов вы бы окончательно лучше с решением, представленным Roger Pate .
То, что вам нужно для общего решения MetaProgramming Type_traits . Вы можете использовать их из повышения, либо поставляемых с вашим STL, если достаточно современно.
namespace detail {
template < class T >
T trim_impl(T &val, const std::tr1::true_type& )
{
if (val < 0)
{
val = 0;
}
return (val);
}
template < class T >
T trim_impl(T &val, const std::tr1::false_type& )
{
return (val);
}
} // end namespace detail
template < class T >
T trim(T &val)
{
return detail::trim_impl( val, std::tr1::is_signed<T>() );
}
Обратите внимание, однако IS_Signed
IS_Signed false_type
для чисел плавающих точек (не спрашивайте почему). Чтобы сделать вышеуказанный код работы с плавающими точками, вам нужно будет типировать еще одну черту, например,
typedef std::tr1::integral_constant< bool,
std::tr1::is_signed<T>::value ||
std::tr1::is_floating_point<T>::value > has_sign;
... и да, глубже вы попадаете в MetaProgramming UUGLIER, он получает так ... игнорировать это решение и перейти с простым, перечисленным Roger: P.
-121--4213573-в зависимости от упрещей, которую я мог бы использовать, либо. Преимущество класса состоит в том, что я могу использовать его как тип и использование типа подсказки на методах или любых методах саморегуления. Если я просто хочу пройти какой-то случайный набор данных от запроса или что-то, я, вероятно, использовал массив. Так что я думаю, пока Фреда имеет особое значение в моей модели, я бы использовал класс.
на Sidenote:
ValueObjects должны быть неизменными. По крайней мере, если вы ссылаетесь на определение Эрика Эвана в домене, управляемый доменом. В Peaea Peaeal ValueObjects не обязательно должны быть неизменными (хотя рекомендуется), но они не должны иметь личность, что ясно в случае с Фред .
Pro для хеша: он способен обрабатывать комбинации значений имени, которые неизвестны по времени проектирования.