Професионална програма
Loading...
StaVykoV avatar StaVykoV 169 Точки

[Java - OOP Advanced - Exercises] Problem08 - MilitaryElite

Здравейте!

Преди малко, докато обмислях контструкцията която трябва да направя за тази задачка, доста се позачудих за класа Soldier и интерфейса който се изисква за него. Ясно ми е, че идеята е да се упражняваме в писането на интерфейси, но ще попитам за принцната ситуация.

Тъй като field-овете на Soldier, по условието на задачата, ще се достъпват само от наследниците му и то за toString() метода. Има ли смисъл да правим гетърите публични и съответно въобще да имаме интерфейс ISoldier?

Поздрави!

П.П. Всъщност ако ползваме гетърите само за toString(), реално ни стигат да са private за всички класове нали?

Тагове:
0
C# OOP Basics 15/07/2016 03:00:18
Ivan_Pashkulev avatar Ivan_Pashkulev 20 Точки

Да, така е, освен за toString() не се достъпват от никъде и могат да са private. Явно идеята е да упражним интерфейсите и да свикнем да програмираме към интерфейси.

0
IvelinTenev avatar IvelinTenev 51 Точки

Поправете ме ако греша, но toString() методите не трябва да са private. Доколкото разбирам, @Override toString() се прави за да дефинира как се отпечатва даден обект. Примерно: System.out.print(soldier)

Също, ако не се лъжа, toString() няма нужда да се декларират в интерфейса, защото се наследяват от Object.

Поздрави,

Ивелин Тенев

0
Ivan_Pashkulev avatar Ivan_Pashkulev 20 Точки

Да прав си, така е - toString си е публичен метод на Object. Няма как да бъде private. Става дума за публичните гетъри от класовете на войниците. Понеже ги пишем към интерфейси, интерфейса ни задължава те да са публични, но иначе за целите на задачата можеше да си останат private защото единственото място където се ползват е в toString() метода на войника. В случая се упражняваме да пишем класовете към интерфейси.

0
IvelinTenev avatar IvelinTenev 51 Точки

Да, не бях разбрал напълно предишния ти пост. Снощи до 3 си играх с това и още не съм се преборил :)

Доколкото разбирам правилата са следните:

  • Ако поле се ползва само от неговия клас, няма нужда от getter към него.
  • Ако имаме getter, няма идея той да не е public. В абстрактните класове property-тата могат да са protected, въпреки че няма голяма идея, тъй като абстрактните класове не могат да се инстанциират.
  • Private пропертита нямат смисъл.

Към ОП: Ако не се лъжа, field-вете на Soldier не трябва да се достъпват от наследниците му, а да се преизползва super.toString() метода.

Поздрави,

Ивелин Тенев

0
17/07/2016 16:29:41
kaloyannikov avatar kaloyannikov 531 Точки

private Properтита има смисъл и дори си е почти задължително за сетърите.

В случая в задачата понеже всички наследници на Soldier имат неговите атрибути 

: Id , firstName , lastName

Няма нужда да имат публични гетъри тъй като единствената им употреба е в класа Soldier , но все пак ако се налага някъде нещо за някой метод е по-добре да го има като гетър и да се достъпва. А и целта е да се упражнят интерфейси в тая задача , затова не можем да избягаме от public

0
17/07/2016 16:37:32
kosio197 avatar kosio197 104 Точки

Привет,

Ето как го разбирам аз:

Когато правим задача с ООП не гледаме да нагодим архитектурата към условието на конкретната задача, защото много често в практиката се налага да се правят разширения. Мислим  какви евентуално задачи могат да дойдат като разширения и как с минимални промени ще можем да ги решим. Тоест, винаги когато един метод е "безопастно" да бъде public го оставяме така. В повечето случаи няма нужда get методите да са скрити, защото няма да стане проблем ако те бъдат прочетени. Set методите, обаче много често могат да създадът проблеми: Например, ако правим клас Person  с id, firstName и  lastName не е проблем тези три полета да се четат, можем да пуснем и public setters за firstName и lastName, тъй като предполагаме, че е възможно човек да си смени първото и последното си име, но не слагаме  public setter за id, защото ако то се смени има голяма вероятност да се счупят различни мапове или листове, които разчитат на това id. За protected полетата по същия начин, само когато могат да доведат до проблем, например: Имаме няколко класа, които имат метод execute и независимо какво прави този метод винаги има примерно try catch или някаква валидация в началото. Съответно искаме да изнесем валидацията и еxecute  в абстрактен клас:

abstract class Test {

public abstract validate();

protected abstract doExecute();

public execute {validate(); doExecute();}

}

Тоест няма проблем клас от вън да валидира, ако обаче оставим doExecute() публичен има голяма вероятност от Exception, т.е. искаме винаги когато се вика doExecute, преди това да се направи валидация на данните.

Подобно е и с вдигането на нивото на абстракция. Задачата може да се реши и с по ниско ниво на абстракция, но мисленето е насочено отново към това какви промени могат да дойдат и как най - лесно да си преизползваме кода. И тук идва трудната част (поне според мен), до къде да се спре с тази абстракция, защото все пак е не възможно да се предвиди всичко, а и не е  ОК да се изпишат тонове код за малка задача.

2
AntonPortenov avatar AntonPortenov 102 Точки

Хубаво е да имаш getters.

От това, което прочетох тези дни много програмисти поставят валидацията в getter-a.

Причината за това е, че перфектна програма няма, и така си спестяваш хвърлянето на exeptions, защото може да не се наложи да иползваш това поле.

0
kosio197 avatar kosio197 104 Точки

Хм, защо валидация в getter? По - скоро в setter, защото реално там се задава стойността, getter-a освен да я върне друго не прави.

"защото може да не се наложи да иползваш това поле."  - това не го разбирам, може ли да поясниш ?

0
AntonPortenov avatar AntonPortenov 102 Точки

Най-добрия вариант е в сетъра, но в сетъра гърми при подаване а в гетъра при пойскване.

Ако подадеш нещо грешно ще ти гръмне още на входа иначе ще ти гръмне когато го извикаш, ако го извикаш.

0
IvelinTenev avatar IvelinTenev 51 Точки

Във връзка с това, трети тест ми гърмеше с IllegalArgument, при създаване на Engineer с невалиден Corp. Пазя Corp в Enum и имам валидация във setter-а, който хвърля еxception, който обработвам при инстанциирането на обекта. Теста ми гърмеше обаче защото се опитвах да взема Corp.valueOf от невалидния вход, преди да го подам на конструктора.

Въпросът ми е, в такива случаи е по-добре да се подават аргументите като стринг, и да се evaluate-ват в setter-ите, или да се прави валидация на входа, освен в setter-а?

Поздрави,

Ивелин Тенев

0
kosio197 avatar kosio197 104 Точки

Според мен не трябва да има  валидация в getters, защото ако ще гърми  там един вид вече си си счупил класа. Валидацията трябва да е в setter-a или конструктура.

Относто enum-a, не мисля, че класа трябва да прима string изобщо (нито в сетърите, нито в конструкторите), директно да си приема enum: void setStatus(Status status) и който ще ползва класа да се погрижи да си набави enum value-то. Същото е като при integer, когато един клас трябва да работи с integer поле, то няма set метод, който приема стринг и вътре прави Integer.valueOf(), който вика класа, той да се грижи да му подаде съответните типивe.

Ето ги мойте имплементации на класа и интерфейса с enum:

https://github.com/kosio197/InterfacesAndAbstraction/blob/master/src/bg/softuni/militaryelite/model/contracts/Mission.java

https://github.com/kosio197/InterfacesAndAbstraction/blob/master/src/bg/softuni/militaryelite/model/MissionImpl.java

1
kaloyannikov avatar kaloyannikov 531 Точки

щом 1 поле няма да ти потрябва изобщо защо мястото му е там ? 

0
kosio197 avatar kosio197 104 Точки

Няма да се наложи в така поставеното условие на задачата, но по - късно може да се наложи при разширение на задачата. А нали все пак трябва да гледаме кода да може да се презиползва, т.е. лесно да се разшири при нови изисквания, нали за това е и това високо ниво на абстракция, което се изисква в тази задача. То реално ако ще е само печата(да минат тестовете на задачата) и се предполага задачата да не се разширява повече, защо изобщо са тези класове и интерфейси? Getter-a на мисията може да потрябва за много неща в последствие, за различни статистики на пример. И там вече ако съм бутнал невалидни мисии какво да го правя като ми гръмне getter-a в последствие, като вече ми е счупена статистиката?

Аз поне така си ги обяснявам тези изсквания, не само в тази, а и в другите задачи по ООП, защото то реално повечето могат да се решат и с един доста прост клас. Може и аз да не съм разбрал правилно, но така ми се струва логично след всичкото писане и четене.

 

0
kosio197 avatar kosio197 104 Точки

@AntonPortenov  "От това, което прочетох тези дни много програмисти поставят валидацията в getter-a.

Причината за това е, че перфектна програма няма, и така си спестяваш хвърлянето на exeptions, защото може да не се наложи да иползваш това поле."

Все още го мисля това. Може ли да дадеш линк към това което си чел?

0