вопрос по ООП

Simplichio

Новичок
вопрос по ООП

В чем смысл подобных конструкций

PHP:
<?php
class Person {
 private $name;
 private $age;
 
 	public function setName($name){
 	$this->name=$name;
 	}
 	public function getName() {
 	return $this->name;
 	}
 
 	public function setAge($age){
 	$this->age=$age;
 	}
 	public function getAge() {
 	return $this->age;
 	}
}
?>
Я понимаю необходимость подобных функций set, если они проверяют корректность вводимых данных, или форматируют эти данные, - что то делают.
Но чем подобный класс лучше, чем
PHP:
<?php
class Person {
 public $name;
 public $age;
}
?>
чем лучше
$obj->setName("Вася");
по сравнению с
$obj->name = "Вася"
я не понимаю.
 

440hz

php.ru
1. поменяется у тебя ->name на ->fio и скока кода править нужно будет?

2. данные нужно защищать, а доступ ->name открытый доступ. сие неправильно.

вообщето это основы ООП.

p.s. если не понимаешь разницы - делай как умные дяди пишут. потом легче будет, когда пойммешь, а не будешь переучиваться.

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

С.

Продвинутый новичок
Похоже "дядя" 440hz, сам не в курсе, почему он так делает. Скорее всего научился у другого "дяди". Так рождаются догматы.

Вопрос у Simplichio совершенно закономерный. С каких это пор в ООП свойствами классов стало пользоваться стыдно и не ООП-ишно? А методами - кульно и единственно правильно?
 

zerkms

TDD infected
Команда форума
потому что свойства раскрывают содержание класса, о котором снаружи ничего известно быть не должно - для этого есть методы (которые описаны интерфейсами)
ну и контроль доступа и изменения конечно же
 

440hz

php.ru
Похоже "дядя" 440hz, сам не в курсе, почему он так делает
почем я так делаю я написал. если кто-то делает по другому - это его законное право.

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

не. конечно можно и напрямую менять свойства. но мне кажется что через методы и красивее и понятнее и безопаснее.
 

Skubent

Новичок
440hz, а что, замена ->senName() на ->setFIO() меньше времени займет, чем чем ->name на ->fio ?
А что, данные сильно защищаются в интерпретируемом языке ? Или, скорее, а что, данные сильно подвержены несанкционированной модификации ?

И, в догонку, а приведешь доказательство того, что методы лучше свойств ? Можно со слов умных дядь, но только с обоснованием.

Simplichio, единственное, зачем такое может понадобиться - это со временем добавить в set* - get* методы проверки и форматирования данных.
Допустим, в классе наследнике переписать сеттеры, чтобы данные удовлетворяли вновь наложенным ограничениям.
 

440hz

php.ru
Skubent


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

=)
 

Skubent

Новичок
440hz, ну то есть мое стремление расти над собой отклика в твоей нежной душе не получило и придется мне оставаться во тьме незнания ответов на мои вопросы...
 

440hz

php.ru
Автор оригинала: Skubent
440hz, ну то есть мое стремление расти над собой отклика в твоей нежной душе не получило и придется мне оставаться во тьме незнания ответов на мои вопросы...
душу оставим в покое.

логического обоснования я тебе не дам. сорри. наверное еще сам не вырос. но подход к объектам через методы, а не на прямую мне более близок чем обращения напрямую к свойствам объекта.

филосовски что ли ... от так ...
 

alexei.lexx

Новичок
Методы - это фактически интерфейс, предоставляемый классом различным пользователям. Именно поэтому и рекомендуется их использовать.

Захочешь ты в прекрасный момент хранить значение параметра name не в свойстве $this->name, а, например, так $this->properties['name'], то интерфейс менять не придётся.

И как уже говорили, всегда легко добавить проверку входных данных.

Кстати свойства можно реализовать так, чтобы на деле вызывались соответствующие set/get методы. Почитайте, кто не знает, про методы __set и __get в PHP 5.

Пример.
Вызов

$person->name = 'Ivan'

приведёт к вызову метода

$person->__set('name', 'Ivan')
 

Skubent

Новичок
alexei.lexx, приведет к вызову метода __* только в случае, если name не будет найден в текущей области видимости (то есть protected свойство при вызове из наследника -для твоего примера- будет установлено напрямую)
 

alexei.lexx

Новичок
Автор оригинала: Skubent
alexei.lexx, приведет к вызову метода __* только в случае, если name не будет найден в текущей области видимости (то есть protected свойство при вызове из наследника -для твоего примера- будет установлено напрямую)
Совершенно верно.
 

FreeSpace

Чукча-читатель
Как тут уже писали, использование геттеров (раз с использованием сеттеров всё понятно) позволяет пользователю класса рассчитывать на то, что интерфейс не поменяется в следующей версии класса, даже если поменяется его внутренняя реализация.

Например, есть у нас класс для работы с датами.
Допустим, в текущей реализации у нас есть два способа получить текущий месяц:
$date = new Date();
echo $date->month; // первый способ
echo $date->getMonth(); //второй способ

Вроде бы всё просто и понятно, но вот в следующей версии класса автор подумал, что заводить кучу свойств типа year, month, day, weekday и т.д. смысла нет.
Можно хранить только timestamp, а уже в реальном времени из него вычислять всё, что понадобится. И пропадут в классе все свойства старые и добавиться только одно новое - timestamp.
По сути для нас - бесполезное и вызов $date->month станет обращением к несуществующему свойству, в то время как код getMonth() автор перепишет и этот вызов будет по-прежнему возвращать текущий месяц, хотя внутренняя реализация изменилась.

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

Введение в пятой версии вещей типа __get() и __set() лично мне напоминает эмуляцию properties из C#, но в C# они реализованы удачнее, ИМХО.
 

С.

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

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

Skubent

Новичок
FreeSpace, аналогично автор может подумать и о том, что getMonth() не нужен - это вопрос совместимости версий и документации/технического задания.
 

hermit_refined

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

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

FreeSpace

Чукча-читатель
С.
Вроде никто не говорит, что все свойства нужно в обязательном порядке обрамлять, ко всему нужно подходить с умом и самостоятельно оценивать, следует ли применять ту или иную методику в каждом конкретном случае.

Skubent
Если getMonth() был public и автор решился его менять, то гнать в шею надо такого автора вместе с его библиотекой :)
Можно возразить, что с тем же успехом автору нельзя убирать свойство $month, если оно изначально было public, но в этом-то и загвоздка: чтобы развязать себе руки, не нужно делать свойства публичными, чтобы потом, при рефакторинге своего класса, не натыкаться на такие грабли.
 

hermit_refined

Отшельник
Лирическое отступление.
Это не обоснование, но забавный (и не для всех тривиальный) пример того, что может случится, если вы будете переходит улицы в неположенном месте.
PHP:
class Test
{
     public $member = 0;
}

$a = new Test;

// ...много кода...

$ref = &$a->member;

// ...много кода...

$b = clone $a;

// ...много кода...

$b->member = 1;

// ...много кода...

echo $a->member, "\n";
Теперь в зависимости от того, присутствует ли строка $ref = &$a->member; или нет, мы получим разный результат.
Можно спросить - зачем здесь вообще было создавать ссылку? Здесь - не зачем, она могла просто случайно остаться от какого-то старого кода, опечатка, мгновенное помрачение рассудка, нелепо выраженное желание иметь возможность проверить значение $a->member, когда $a выйдет за пределы видимости...
Но нарушение инкапсуляции здесь приводит к ошибке, которую очень сложно отловить, тем более, если эти строки разнесены по разным классам.
 

С.

Продвинутый новичок
Ага, наконец-то я понял, зачем вам ООП!

Чтобы при любых помрачениях рассудка кодера, опечатках, остатков ненужного кода, спонтанных сменах названий свойств, скрипт продолжал бы работать, как положено в ТЗ.

А потом появляются темы, как народ поносит своих предшественников за кривые скрипты.
 
Сверху