Loading...
t.316 avatar t.316 137 Точки

[Homework] Inheritance and Abstraction (Nov 2015) - Решения

Здравейте!

Това е моят вариант за решение на задачите от домашното: https://github.com/T316/OOP/tree/master/05.%20InheritanceAndAbstraction

Ще се радвам на всякакви коментари и препоръки, както и да видя вашите варианти за решение на задачите.

Тагове:
2
C# OOP Basics
ickata2112 avatar ickata2112 12 Точки

Здравей, на втора задача не е ли по-правилно да използваш:

a => a is Dog

вместо

a => a.GetType().ToString() == "Animals.Dog"?

0
25/11/2015 01:42:21
Filkolev avatar Filkolev 4482 Точки

На Count() от LINQ може да му се подаде ламбдата и да стане с един метод. 

Аналогично може да се сметне и средното с Average като му се посочи да сметне средната възраст.

0
Filkolev avatar Filkolev 4482 Точки

Относно коригирания ти коментар в такъв случай.

Как е правилно да се провери типа зависи от ситуацията. is операторът ще провери дали обекът е от класа или от клас наследник на типа отдясно. Често точно това е случаят.

Ако обаче целта е да се провери за конкретен клас, без наследниците му, трябва да се направи нещо такова: if (dog.GetType() == typeof(Dog))

Проверката с името и стринговия литерал не е много правилна освен ако ситуацията не го налага (примерно получаваме някакъв стринг, който е име на клас). Но в този случай пак има по-правилен подход - dog.GetType().Name == "Dog". Друг вариант е да се ползва рефлекшън, което вече е малко по-сложна материя, но с една дума може имайки стринга "Dog" да намерим типа и да приложим проверката от по-горе с typeof().

2
t.316 avatar t.316 137 Точки

Кагато правих 2 задача много се чудих как може да се направи по-правилно, но така и не се сетих. Сега вече го промених да е с typeof. 

Благодаря за обяснението.

0
butanfire avatar butanfire 32 Точки

Относно третата задача - мисля че трябва да имплементираш повече Интерфейси.

Защо? :))

Защото го изискват -> Extract interfaces for each class.

 

=> Демек , трябва да имаш interface ICustomer с 1 поле :))))

Същото е за IProject , ISale ... и т.н. :)

 

Поздрави,

Владо

 

 

0
t.316 avatar t.316 137 Точки

Изобщо не бях обърнал внимание, че трябва на всичките класове. Вече го оправих.

Благодаря!

0
Filkolev avatar Filkolev 4482 Точки

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

4
djc_bg2015 avatar djc_bg2015 923 Точки

Прав си. Не го бях поглеждал от тази гледна точка :)

0
vlastanov avatar vlastanov 2 Точки

Имам 3 въпроса от задача 3 към djc_bg2015

 1.Интерфейсите ти се разширяват един с друг.Имаш и абстрактни класове ,които се наследяват един с друг?Защо тогава интерфейсите трябва да се разширяват?

2.В класа Manager:

(1) public IList<IEmployee> Employees => this.employees;

(2) public IList<IEmployee>  Employees

        {

            get { return this.employees;}

        }

(1) и (2) едно и също ли е?

3.Клас Manager пази списък от Employee.Не използваш конструктор,нито метод ,за да добавяш елементи в него.Как тогава ще се използва този списък?

0
djc_bg2015 avatar djc_bg2015 923 Точки

@t.316

- На задача 2 можеш сериозно да опростиш сортирането по средна възраст, до буквално 1 линк заявка.

- Пак на задача 2, е можело да override-неш тустринга на клаосвете и в мейна само да ги печаташ.

- На задача 3 не си изнесъл публичните свойства на класовете в интерфейси (поне не на всички).

 

Поздрави!

1
t.316 avatar t.316 137 Точки

За трета задача просто не бях обърнал внимание, че трябва на всички класове да се добави интерфес.

Втора я оправих, като използвах част от кода на твоето решение. Беше ми много полезно.

Благодаря ти!

0
G.nikolovv avatar G.nikolovv 5 Точки

Абстрактния клас не може да се инстанцира затова няма смисъл да му правиш конструктор.Той ти носи само информацията която трябва да бъде наследена. И вече в наследниците инициализираш пропъртитата.

public class Dogs:Animal
    {
        public Dogs(string name,int age,string breed)
        {
            this.Name = name;
            this.Age = age;
            this.Breed = breed;
        }

        public override void ProduceSound()
        {
            Console.WriteLine("Bark!");
        }

 

Примерно:)

0
RoYaL avatar RoYaL Trainer 6849 Точки

False info. Абстрактният клас не може да се инстанцира, НО това не значи, че няма смисъл да му правиш конструктор. Ако всичките наследници на абстрактния клас ще споделят една и съща логика за конструиране на обекта, като например да се инициализират 20 пропъртита, то е по-добре тази логика да бъде изнесена в конструктура на абстрактния клас, а неговите наследници да наследяват конструктура експлицитно използвайки делегирането на параметри с base(param1, param2...)

P.S.: Не си кръщавай класовете в множествено число.

5
G.nikolovv avatar G.nikolovv 5 Точки

Вярно :). Мерси за tip-a. 

И все пак ако кажеш, че не искаш животните да имат името "Пешо", но Dog и Frog могат да се казват така, трябва да си се направи отделна логика в класовете Dog и Frog?

0
25/11/2015 14:55:37
valiobar avatar valiobar 29 Точки

Ето и моят вариант на 3та задача .https://github.com/valiobar/12345

0
Blaskowitzzz avatar Blaskowitzzz 41 Точки

Аз имам въпрос относно 3-та задача:

При положение, че класовете Employee, Customer, и т.н. наследяват Person, нужно ли е интерфейсите им да се имплементират един друг:

пр. public interface IEmployee : IPerson, и т.н.?

Ето и моите решения:

Задача 1

Задача 2

Задача 3

0
Filkolev avatar Filkolev 4482 Точки

Нужно е да. Интерфейсите съществуват независимо от класовете, които ги имплементират. Никой не е длъжен когато си прави клас CustomEmployee примерно заедно с имплементирането на интерфейса IEmployee да наследи и някакъв клас. 

Когато казваш, че IEmployee екстендва IPerson, ти задължаваш всеки клас, който имплементира IEmployee да имплементира и членовете на IPerson. Ако не направиш това екстендване, може някой да имплементира IEmployee, без обаче да имплементира каквото и да било от IPerson и без да наследи Employee класа, който наследява Person. Т.е. може да попаднеш в ситуация някой да създаде някакво IEmployee, което няма поведението на IPerson, което не е правилно. 

1
Cocolino avatar Cocolino 36 Точки

На 2-ра задача е необходимо да изведеш средната възраст поотделно за всеки тип животно, а не на всички, които си вкарал в масива animals.

0
krisi1606 avatar krisi1606 33 Точки

Аз искам да попитам нещо за трета задача;
Значи, казва се:

  • Manager – holds a set of employees under his command.

тоест си правим лист от Employees, но в интерфейса това

List<Employee> Employees { get; set; }

или това

List<IEmployee> Employees { get; set; }

трябва да напишем и каква е логиката зад отговора. И после, ако случаят е <IEmployees> как трябва да работим с този лист?

1
Filkolev avatar Filkolev 4482 Точки

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

Винаги е хубаво да се работи през най-абстрактното нещо, което ти върши работа, а това са интерфейсите. Като цяло интерфейс да депендва на конкретен клас не е много правилно, но дори и в рамките на обикновен клас по-правилното решение е да се направи List<IEmployee>. Може да вдигнеш още абстракцията като ползваш IList<IEmployee> или в зависимост от нуждите - ICollection или нещо друго. Аз бих избрал в случая IList<IEmployee>, така давам свобода на този, който ползва интерфейса, да си напълни някаква негова колекция, не задължително списък, с някакви служители, които не са задължително от класа Employee.

1
krisi1606 avatar krisi1606 33 Точки

Супер, мерси за обяснението. Предполагам същата логика важи и за другите класове, които държат листове от Sales,  Projects and etc.  Благодаря!

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.