Static property vs method

SVTerziev

Registered
Интересува ме дали единия вариант е по-добър от другия и защо:

PHP:
trait TDog {
    private static $type = 'dog'; 
}

abstract class Animal {
    protected $name;
    protected $age;

    function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
}

class Dog extends Animal {
    use TDog;

    public function __construct($name, $age) {
        parent::__construct($name, $age);
    }

    function show() {
        echo 'We have a '. self::$type .' called '. $this->name .' at the age of '. $this->age;
    }
}

$doggy = new Dog('Dod', 12);
$doggy->show();
PHP:
trait TDog {
    private function getType() {
        return $this->type = 'dog';
    }
}
...
...
    function show() {
        echo 'We have a '. $this->getType() .' called '. $this->name .' at the age of '. $this->age;
    }
}
...
 
Мисля, че с метода ще ти е по-добре. Защо смятам така?! Ами реално защото на метода можеш да подадеш някаква променлива и можеш да я промениш когато пожелаеш. Дава ти гъвкавост на кода докато статичната прайвът променлива не ти позволява тази гъвкавост. Например:
PHP:
trait TDog {
    private function getType($type = 'dog') {
        return $this->type = $type;
    }
}
...
...
    function show() {
        echo 'We have a '. $this->getType() .' called '. $this->name .' at the age of '. $this->age;
echo 'We have a '. $this->getType('cat') .' called '. $this->name .' at the age of '. $this->age;
    }
}
...

Разбира се това зависи от логиката ти но наистина реално ти можеш да си правиш всякакви проверки и логики докато при статичната променлива нямаш тази гъвкавост. Имаш я ако я поставиш отново в метод което пък става вече дълго и широко и пак ще стигнеш до най-простата разновидност а именно тази. :)
 
И аз така си мислех, но беше хубаво да чуя още едно мнение, благодаря. :?:
 
Хмзз. Тука нещо ми се изгуби логиката ...

Първо, защо в trait ги правиш тези врътки ... По принцип trait-a трябва да си го ползваш за да добавяш някакъв общ bihavior на клас, а от примера ти нещо не хванах идеята. Както и да е.

По темата според мене е по-добре да ползваш getter вместо статично propperty в случай, че ще имаш нужда от промяна на данните или някакво санитизиране в последствие, ако е за някакви статични цели не виждам смисъл.

Иначе статични константи е удобно да се ползват примерно при описание на типове за нещо ( вместо да тъпчеш БД ).
 
Може би заради примера, но ми убягва идеята за какво ти е този TDog trait.

Би ли пояснил?
 
eLite каза:
Може би заради примера, но ми убягва идеята за какво ти е този TDog trait.

Би ли пояснил?
Няма как дал е точка, но явно просто пример е дал някакъв там за да може да го разберем по-точно какво иска. :)
 
PHP:
 private function getType($type = 'dog') {
        return $this->type = $type;
    }

Това винаги ще връща или "dog" или пуснатото като параметър.

Освен това в getter метод се задава стойност на свойство. Това е много грешно.


Виж примери как се ползва:
PHP:
trait TBreed
{
	private $breed; // Порода - нещо което се отнася само за кучета

	public function setBreed($breed)
	{
		$this->breed = $breed;
		return $this;
	}

	public function getBreed()
	{
		return $this->breed;
	}

}


class AnimalTypes
{
	const TYPE_DOG = 'dog';
}

class Animal
{
	private $type;
	private $name;

	function __construct($type, $name)
	{
		$this->type = $type;
		$this->name = $name;
	}

	public function getType()
	{
		return $this->type;
	}

	public function getName()
	{
		return $this->name;
	}

	public function setName($name)
	{
		$this->name = $name;
		return $this;
	}
}

class SmallDog extends Animal
{
	use TBreed;

	private $color;

	public function __construct($name)
	{
		parent::__construct(AnimalTypes::TYPE_DOG, $name);

	}

	public function getColor()
	{
		return $this->color;
	}

	public function setColor($color)
	{
		$this->color = $color;
		return $this;
	}
}


$my_dog = (new SmallDog("Sharo"))
	->setBreed('StreetImproved')
	->setColor('white');
 
gamena007 каза:
PHP:
 private function getType($type = 'dog') {
        return $this->type = $type;
    }

Това винаги ще връща или "dog" или пуснатото като параметър.

Освен това в getter метод се задава стойност на свойство. Това е много грешно.


Виж примери как се ползва:
PHP:
trait TBreed
{
	private $breed; // Порода - нещо което се отнася само за кучета

	public function setBreed($breed)
	{
		$this->breed = $breed;
		return $this;
	}

	public function getBreed()
	{
		return $this->breed;
	}

}


class AnimalTypes
{
	const TYPE_DOG = 'dog';
}

class Animal
{
	private $type;
	private $name;

	function __construct($type, $name)
	{
		$this->type = $type;
		$this->name = $name;
	}

	public function getType()
	{
		return $this->type;
	}

	public function getName()
	{
		return $this->name;
	}

	public function setName($name)
	{
		$this->name = $name;
		return $this;
	}
}

class SmallDog extends Animal
{
	use TBreed;

	private $color;

	public function __construct($name)
	{
		parent::__construct(AnimalTypes::TYPE_DOG, $name);

	}

	public function getColor()
	{
		return $this->color;
	}

	public function setColor($color)
	{
		$this->color = $color;
		return $this;
	}
}


$my_dog = (new SmallDog("Sharo"))
	->setBreed('StreetImproved')
	->setColor('white');

Колега, това е просто пример за да му обясня по-нагледно какво имах предвид. Това което казваш е така и не е така същевременно. Защо? Не е така защото зависи от случая и логиката в приложението. Ако ти трябва да връща някаква дефаутова стойност на този параметър и същевременно му подаваш стойности на различни места в кода не е проблем да ползваш този начин. Твоят варянт е правилен също, но да твърдиш: "Това е много грешно." e глупаво. Зависи от случая. Ако става дума веднага ще ти кажа, че твоят варянт презаписва стойността и дефаутовата се променя тоест новата става дефаутова до друга промяна и така нататък. Твоята пък е изписване на допълнителен код и още много дивотии, но предлагам да не задълбаваме. И двамата сме прави защото в името на примера обясняваме две различни ситуации. :?:
 
Ако получа проект, в който getter set-ва стойност, ще знам на кого е. :v
 
@dakata__92, извинявай ако съм те засегнал. Коментарът ми нямаше такава цел.


Относно това:


private function getType($type = 'dog') {

return $this->type = $type;

}


Грешки:
1. Private getter method
2. Getter метод променя property
3. Getter метод връща резултат пуснатият към него параметър


В общи линии това са три реда код с три грешки в тях.
 
gamena007 каза:
@dakata__92, извинявай ако съм те засегнал. Коментарът ми нямаше такава цел.


Относно това:


private function getType($type = 'dog') {

return $this->type = $type;

}


Грешки:
1. Private getter method
2. Getter метод променя property
3. Getter метод връща резултат пуснатият към него параметър


В общи линии това са три реда код с три грешки в тях.
По точка едно в бързината на коментара съм го драснал, грешката е моя.
По другите инстанциии пак казвам зависи много ама много от приложението.
Който е изучавал методи за оптимизация ще се досети. Така нагледно да обясня.
PHP:
class Sounds{
	private $sound;
	
	public function getSound($sound = 'woof'){
		return $this->sound = $sound;
	}
	
}

$i = new Sounds();
echo 'The dog says '.$i->getSound().'.';
echo '<br>The cat says '.$i->getSound('meow').'.';
echo '<br>The dog says '.$i->getSound().'.';
Ето един клас. Както виждаш аз взимам дефаутовата стойност на параметъра на getSound която е woof. В един от случаите ми е нужно да взема просто някаква стойност за котката. Подавам на параметъра гет тази стойност и той ми я връща. Къде видяхте сетване на $this->sound извън getSound? Той винаги ще е false ако не съм викал гет. Давам друг пример, който води до същият резултат по вашата схема.
PHP:
class Sounds{
	private $sound;
	
	public function setSounds($sound){
		$this->sound = $sound;
	}
	
	public function getSound(){
			return $this->sound;
	}
	
}

$i = new Sounds();
$i->setSounds('woof');
echo 'The dog says '.$i->getSound().'.';
$i->setSounds('meow');
echo '<br>The cat says '.$i->getSound().'.';
$i->setSounds('woof');
echo '<br>The dog says '.$i->getSound().'.';
Това сетване е излишно писане ако знам, че ще връщам някакаква дефаутова стойност на параметъра. Кое му е оптимизираното? Хващате се за някакво название на метода но ако го кръстя returnSound() ще кажете да може да стане така. Варянти и разновидности има много, но не казвай, че това е грешна практика, само защото съм кръстил някакъв метод get. Ти реално взимаш стойността на паръметъра на getSound и имаш възможността да подадеш друга стойност на параметъра и според логика да върнеш друго. Има много вариациии на кодовете примерно сещам се веднага за поне 5,6 варянта за достигане до същите резултати:
PHP:
class Sounds{
	private $sound = 'woof';
	
	public function setSounds($sound){
		if(!empty($sound)){
			$this->sound = $sound;
		}
	}
	
	public function getSound(){
			return $this->sound;
	}
	
}

$i = new Sounds();

echo 'The dog says '.$i->getSound().'.';
$i->setSounds('meow');
echo '<br>The cat says '.$i->getSound().'.';
$i->setSounds('woof');
echo '<br>The dog says '.$i->getSound().'.';

За мен това е едно така оптимизирано решение, бързо което дадох, което за стотен път ще кажа, че връща ДЕФАУТОВА стойност. Защо се хващате за примера ми, когато човекът към който съм го драснал схвана идеята ми. Писал съм го тук по между работата ми и прочие.
class Sounds{
private $sound;

public function getSound($sound = 'woof'){
return $this->sound = $sound;
}

}

$i = new Sounds();
echo 'The dog says '.$i->getSound().'.';
echo '<br>The cat says '.$i->getSound('meow').'.';
echo '<br>The dog says '.$i->getSound().'.';
Бързо, лесно и без нуждата да създавам отделен сетер тоест метод да сетва променливата си свършвам същата работа. Един професор преди време ми каза, че когато следваш пътя на стериотипа не виждаш пътеката до върха. Оптимизацията е вид вариация на дадено действие просто подобрено. Сега, според вас ако не е подобрено това е вашо виждане, но за моите расъждения си е спестяване на код. Ако на някакво приложение трябва да сетна 10 променливи тоест нещо нещо подобно трябва да изписвам на всяка променлива метод а после и да го викам. Сега не успорвам, че това което казвате не е правилно. Напротив в много от случаите го използвам и така нататък, но това зависи от логиката, от самото приложение и от още десетки фактори. В случаят от последно даденият от мен код (public function getSound($sound = 'woof'){) когато викам private $sound; в класът да ми върне стойността той винаги е woof за метода, но ако реша да създам трети метод в който да използвам променливата тя ще бъде FALSE защото няма да е сетната и тогава вече може да се използва некакъв сетер да и подава стойност, като със съвсем малко логика в гет можете да направите пак супер гъвкав код. Но както и да е ще дам и едно друго примерче в подкрепа на вашата теза:
PHP:
class Sounds{
	private $sound;
	private $animal;
	
	public function setSound($sound){
		$this->sound = $sound;
	}
	
	public function getSound(){
		return $this->sound;
	}
	
	public function animal(){
		switch($this->sound){
			case 'woof':
				return $this->animal = 'dog';
				break;
			case 'meow':
				return $this->animal = 'cat';
				break;
		}
	}
	
}

$i = new Sounds();
$i->setSound('woof');
echo 'The '.$i->animal().' says '.$i->getSound().'.';
$i->setSound('meow');
echo '<br>The '.$i->animal().' says '.$i->getSound().'.';
$i->setSound('woof');
echo '<br>The '.$i->animal().' says '.$i->getSound().'.';

Така сега ще постна и недостатък на моята логика е така просто заради примера, за да покажа, че и тя не е универсално решение. Все пак ще отбележа, че metoda анимал се вика преди гет което пък нали указва влияние в логиката. :)
PHP:
class Sounds{
	private $sound;
	private $animal;
	
	public function getSound($sound = 'woof'){
		return $this->sound = $sound;
	}
	
	public function animal(){
		switch($this->sound){
			case 'woof':
				return $this->animal = 'dog';
				break;
			case 'meow':
				return $this->animal = 'cat';
				break;
		}
	}
	
}

$i = new Sounds();
echo 'The '.$i->animal().' says '.$i->getSound().'.';
echo '<br>The '.$i->animal().' says '.$i->getSound('meow').'.';
echo '<br>The '.$i->animal().' says '.$i->getSound().'.';

Но следвайки логиката веднага идва вариацията на примера:


PHP:
class Sounds{
	private $sound;
	private $animal;
	
	public function getSound($sound = 'woof'){
		return $this->sound = $sound;
	}
	
	public function animal(){
		switch($this->sound){
			case 'woof':
				return $this->animal = 'dog';
				break;
			case 'meow':
				return $this->animal = 'cat';
				break;
		}
	}
	
}

$i = new Sounds();
echo ucfirst($i->getSound()).' is said by the '.$i->animal();
echo '<br>'.ucfirst($i->getSound('meow')).' is said by the '.$i->animal();
echo '<br>'.ucfirst($i->getSound()).' is said by the '.$i->animal();

Заключението е, че всички сме прави, зависейки от логиката и ситуацията в приложенията, които създаваме! :?: :?: :?:
 
@dakata__92, отдалечил си се много от идеята зад ООП. Ще ти препоръчам да прочетеш в интернет няколко статии свързани с ООП и добри практики с ООП.

Замисли се над примера, който си дал. За какво ти е клас Sounds? Добра практика е имената на класовете да бъдат в единствено число, тъй като от тях ще се създават множество обекти от такъв тип. Примерно Animal.

В този клас Animal, трябва да имаме частно (private) свойство звук. Тъй като животните рядко смеят издаваният от тях звук, задаването му става еднократно при инициализацията или при промяна в бъдеще чрез setter (setSound).

Идеята на този клас, е че имаш много обекти от него -> Animal (котка), Animal(куче) и т.н.

В последващо обхождане на колекция от обекти от тип Animal, ти ще викаш само getSound(), което само и единствено връща частният метод.

Ако искаш да смениш някой звук, трябва да го правиш само и единствено през setter-a. Това е много важно, защото когато върху кода работят повече хора, какво правим? Всеки път трябва да се чудим, този коректен синтактично код, как работи, как да променим или защо е там. Към този абзац искам да отбележа, че разлика между голям и малък проект няма. Ако програмистите са добри, ще могат да работят лесно както сами, така и 200 човека едновременно (в момента работим 4 човека върху един проект).

Много е важно да се пише DRY (Don't Repeat Yourself) и четим код. Преди две години попаднах на един проект, на който клиент искаше да му интегрираме виртуален пос терминал. Сайтът беше писан на CodeIgniter (ок, можеше да е и по-зле), но без никакви стандарти. Беше някакъв ужас. Отне ми 2 часа да разбера логиката зад написаният код. Някой, който е "жупал" код ей така, ми загуби време за много пари.

Работил ли си по големи проекти? В някоя фирма или нещо?
 

Back
Горе