Архив за етикет: ООП

Telerik Homeworks: OOP course – OOP Fundamental Principles – Part 1 (Принципи на ООП – част 1 )

Templates--CShar-OOPОбяснение на задачите/упражненията от домашното към лекцията Принципи на ООП – част I от курса ООП в Академията. Засягат се основни и много важни теми като наследяването на класовете, абстракцията, интерфейсите и тяхното значение, енкапсулацията на данните, как да си направим клас диаграми във VS, така че по-лесно да се ориентираме кой клас от кого точно се наследява и т.н.

{ Кодът с решенията към всяка една от задачите можете да видите тук }

1. We are given a school. In the school there are classes of students. Each class has a set of teachers. Each teacher teaches a set of disciplines. Students have name and unique class number. Classes have unique text identifier. Teachers have name. Disciplines have name, number of lectures and number of exercises. Both teachers and students are people. Students, classes, teachers and disciplines could have optional comments (free text block).
Your task is to identify the classes (in terms of  OOP) and their attributes and operations, encapsulate their fields, define the class hierarchy and create a class diagram with Visual Studio.

ОБЯСНЕНИЕ:  Първото нещо, което правя  е class-а за класа да го кръстя SchoolInClass, за да не се бърка със системния Class. Този клас, както и класа School и Human (в условието се казва, че Учителят и Студента са „people“ т.е. наследяват общ клас) ги правя абстрактни, за да не може от тях да се инстанцират нови обекти. Студентът и Учителят ще наследяват класа Human. Относно метода за Коментари е доста трудно да се определи, дали да бъде направен чрез интерфейс, абстрактен метод или vurtual метод…Аз предпочетох да го направя с интерфес IComment.

2. Define abstract class Human with first name and last name. Define new class Student which is derived from Human and has new field – grade. Define class Worker derived from Human with new property WeekSalary and WorkHoursPerDay and method MoneyPerHour() that returns money earned by hour by the worker. Define the proper constructors and properties for this hierarchy. Initialize a list of 10 students and sort them by grade in ascending order (use LINQ or OrderBy() extension method). Initialize a list of 10 workers and sort them by money per hour in descending order. Merge the lists and sort them by first name and last name.

ОБЯСНЕНИЕ:  Cъздавам абстрактен клас Human (по условие се изисква, а и не е редно класа Human да се инстанцира), който се явява баща на класовете Student и Worker. В тях си слагам полетата и пропъртитата, така както са описани по условието. Добавям и конструктора тук, за да си спестя последващо писане при наследяването от другите класове, като не го правя public, а protected, за да се ползва само от наследниците. Правя си съответните валидации. Оverride-ването на ToString() метода го правя първо в Human, а след това и в Student и Worker с новите им полета. По интересното в тази задача е обединението на двата листа от студенти и работници, като аз го правя с List<Human> и после чрез AddRange ги обединявам в един лист. Различните сортирания на студентите и работниците ги правя чрез LINQ (OrderBy).

3. Create a hierarchy Dog, Frog, Cat, Kitten, Tomcat and define useful constructors and methods. Dogs, frogs and cats are Animals. All animals can produce sound (specified by the ISound interface). Kittens and tomcats are cats. All animals are described by age, name and sex. Kittens can be only female and tomcats can be only male. Each animal produces a specific sound. Create arrays of different kinds of animals and calculate the average age of each kind of animal using a static method (you may use LINQ).

ОБЯСНЕНИЕ:  Animal е базов абстрактен клас за всички животни. Kitten и Tomcat наследяват класа Cat, който не съм го направил да е абстрактен (т.е. може да си има просто инстанция на класа Cat). В интерфейса ISound се помещава метода ProduceSound, който кара животните да говорят, всяко според типа си, който го взимаме чрез GetType().Name. За определяне на пола използвам енумерация, като за Kitten и Tomcat той е фиксиран по условие още в констуктора. Задължително статичният метод по условие AvarageAge съм го поместил в класа Animal, който прави свойте изчисленията си чрез LINQ израз (.Avarage).

Кодът към всяка една от задачите можете да видите тук.

C# OOP: полезни бележки и трикове преди изпита по ООП в Telerik Academy

Templates--CShar-OOPС наближаване на изпита по ООП в Академията, подготвяйки се за него реших да нахвърлям някой бележки, които ги поствам тук, току-виж са ви от полза и на вас 🙂

Инсталирайте си StyleCop към Visual Studio-то – програмката е много удобна и полезна от гледна точка на това да форматирате кадърно вашия год, което пък за изпита по ООП си е важно, тъй като това се гледа и оценява. Използването на StyleCop е много лесно – просто цъкате с дясно копче на мишката върху cs  файла, който искате да проверите, избирате Run StyleCop и програмката ви изплюва предупреждения по синтаксиса на кода ви в Error List панела на VS, откъдето да си ги прегледате и съответно да решите дали да ги взимате под внимание. От менюто StyleCop Settings можете да си включвате/изключвате за какви „грешки“ по  синтаксиса на кода ви да следи програмата.

Run-StyleCop

Инсталирайте си CleanProjectТъй като специално за този изпит BGcoder вече приема ZIP файлове с решението на задачите по ООП, като преди това трябва да се изтрият /bin/ и /obj/ папките. Можете да използвате CleanProject, който значително ще улесни цялото това триене на папки и zip-ване. На сайта му има подробно описание как се използва.

Пинвайте важните табове на отделен ред – когато работите с много класове във Visual Studio е нормално табовете ви горе да се претрупат и навигацията да става трудно. Може да пинвате на отделен ред по-важните. Това става като отидете в менюто Tools  – Options – Tabs and Windows – слагате отметка на Show pinned tabs in a separate row.

oop-visualstudio

За създаването на поле с пропъртитата към него напишете prop последвано от 2 табулации. Това ще изведе:

    public int MyProperty { get; set; }

За създаването на поле с пълния синтаксис за пропърти към него (което ще ви е от полза, ако искате да направите валидация) напишете propfull последвано от 2 табулации. Това ще изведе:

    private int myVar;
    public int MyProperty
    {
        get { return myVar; }
        set { myVar = value; }
    }
За по лесна навигация можете да натискате TAB клавиша, като по този начин, ако да кажем смените int на decimal в полето, това автоматично ще го смени и в пропъртито.
Шортъкът Ctrl + K + D във Visual Studio подравнява автоматично кода ви и го форматира правилно доколкото му е възможно.От гледна точка на добрата практика, ето как е по-правилно да се позиционират отделните компоненти в класа според StyleCop:

Within a class, struct or interface: (SA1201 and SA1203)

  • Constant Fields
  • Fields
  • Constructors
  • Finalizers (Destructors)
  • Delegates
  • Events
  • Enums
  • Interfaces
  • Properties
  • Indexers
  • Methods
  • Structs
  • Classes

Within each of these groups order by access: (SA1202)

  • public
  • internal
  • protected internal
  • protected
  • private

Within each of the access groups, order by static, then non-static: (SA1204)

  • static
  • non-static

Within each of the static/non-static groups of fields, order by readonly, then non-readonly : (SA1214 and SA1215)

  • readonly
  • non-readonly

Още към  добрата практика се счита:
1. Името на променливата в полето да се пише с малка буква.

2. Автоматичното пропърти трябва да е с главна буква

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

4. Параметрите на Конструктора е хубаво да се именуват като стандартни променливи, по-възможност различни от тези в полетата, за да е по-лесно ориентирането после.

За проверки при валидация от тип:
if (firstName != string.Empty && firstName.Length >= 2)

може да се замени със String.IsNullOrWhiteSpace(value)

Използвайте diff tool за сравняване на текстовите файлове с изходните данни
Макар и цялата ви задача да е решена както трябва, дори само заради една запетайка или празно пространство някъде из вашите изходни данни, може BGcoder при тестовете упорито да отказва да ви даде максималния брой точки. Освен да псувате, използвайте и diff tool сайтовете (www.diffnow.com, text-compare.com и др.), които сравняват два текстови файла дали са абсолютно еднакви, и ако не са ви подчертава разликите, дори и празните пространства, които с просто око трудно се виждат.

C# OOP: 101 LINQ Samples

Templates--CShar-OOPПопаднах на този много полезен линк от MSDN, съдържащ цели 101 готови LINQ израза:

„Learn how to use LINQ in your applications with these code samples, covering the entire range of LINQ functionality and demonstrating LINQ with SQL, DataSets, and XML.“

C# OOP: разликата между модификаторите за достъп

oop access modifiers

Готина картинка, която по забавен начин показва разликата между модификаторите за достъп Private, Protected и Public при обектно ориентираното програмиране.

Източник: mvark.blogspot.com

Telerik Homeworks: OOP course – Defining Classes Part 1 ( Дефиниране на класове Част 1)

Templates--CShar-OOPОбяснение на задачите/упражненията от домашното към лекцията Дефиниране на класове Част 1 от курса ООП в Академията. Целта тук е да упражним как става самото дефиниране на класете, слагането на полета, пропъртитата, модификаторите за достъп, как се ползват конструкторите, какво е енумерацията (Enumerations (Enums))  и т.н. Домашното се състои от 12 задачи, които обаче се отнасят за един общ проект т.е. задачите са си свързани помежду си.

{ Кодът с решенията към всяка една от задачите можете да видите тук }

1. Define a class that holds information about a mobile phone device: model, manufacturer, price, owner, battery characteristics (model, hours idle and hours talk) and display characteristics (size and number of colors). Define 3 separate classes (class GSM holding instances of the classes Battery and Display).

ОБЯСНЕНИЕ:  Създаваме си нялкоко полета (fields), като е си е направо задължително те да са private, а не public! Във Visial Studio има страхотни бързи шорткъти, за по-бързо писане на полета:
– За създаването на поле с пропъртитата към него напишете prop последвано от 2 табулации. Това ще изведе:

    public int MyProperty { get; set; }

– За създаването на поле с пълния синтаксис за пропърти към него (което ще ви е от полза, ако искате да направите валидация) напишете propfull последвано от 2 табулации. Това ще изведе:

    private int myVar;
    public int MyProperty
    {
        get { return myVar; }
        set { myVar = value; }
    }

2. Define several constructors for the defined classes that take different sets of arguments (the full information for the class or part of it). Assume that model and manufacturer are mandatory (the others are optional). All unknown data fill with null.

ОБЯСНЕНИЕ:  Тук трябва да се упражнят конструкторите, като основното е да се запознаем с DRY (Don`t repeat yourself) принципа, според който трябва да се избягва повторението на един и същи код. Поради тази причина използвайки „this“ надграждаме конструктора public GSM, без да пействаме всеки път един и същи код в тялото му т.е. всеки нов конструктор наследява кода от предишните (преизползваме предишните конструктори).

3. Add an enumeration BatteryType (Li-Ion, NiMH, NiCd, …) and use it as a new field for the batteries.

ОБЯСНЕНИЕ:  Добавяме обикновена енумерация за батериите („public enum BatteryType“), в която да се съдържа някакъв списък от батерии.

4. Add a method in the GSM class for displaying all information about it. Try to override ToString().

ОБЯСНЕНИЕ:  Всеки обект си има .ToString метод. За да ни връща обаче исканото в условието инфо за даден обект (в случая някакъв телефон примерно), трябва този метод да го overridе-нем и изрищно да му кажем, какво искаме точно да ни връща като информация.

5. Use properties to encapsulate the data fields inside the GSM, Battery and Display classes. Ensure all fields hold correct data at any given time.

ОБЯСНЕНИЕ: Капсулацията на данните се получава, чрез get и set на пропъртитата т.е. там може да се направи валидацията на данните, които се подават към полетата (който задължително трябва да са privаtе). Могат да се направят всевъзможни валидации на данните, в зависимост от нуждите. Между другото, според изискванията в задача 2 към настоящия проект, null в конкретния ни случай се води като коректна стойност за някой от полетата ни.

6. Add a static field and a property IPhone4S in the GSM class to hold the information about iPhone 4S.

ОБЯСНЕНИЕ:  Идеята тук е да се направи статично поле, в което да се съхранява информация за iPhone4S, която може да се ползва всеки път, когато създаваме обект от тип GSM.IPhone4S (подобно на Int32.MaxValue, което също е static field в структурата Int32).

7. Write a class GSMTest to test the GSM class:

– Create an array of few instances of the GSM class.

-Display the information about the GSMs in the array.

– Display the information about the static property IPhone4S.

ОБЯСНЕНИЕ:  Трябва да направим масиви от различни стойности, с които да тестваме конструктора GSM. Подаваме му стойностите чрез един for цикъл и гледаме дали валидацията, която написахме по-горе ще сработи.

8. Create a class Call to hold a call performed through a GSM. It should contain date, time, dialed phone number and duration (in seconds).

ОБЯСНЕНИЕ:  Cъздаваме си нов клас Call, в който подобно на класа GSM си съдаваме privаte полета и конструктор Call.

9. Add a property CallHistory in the GSM class to hold a list of the performed calls. Try to use the system class List<Call>.

ОБЯСНЕНИЕ:  Cлагаме ново поле (private List<Call> callHistory) и ново пропърти (public List<Call> CallHistory {}) в класа GSM.

10. Add methods in the GSM class for adding and deleting calls from the calls history. Add a method to clear the call history.

ОБЯСНЕНИЕ:  От нас се иска да добавим три метода, който да добавят (AddCall), трият (DeleteCall) и изчистват call хронологията (ClearCallHistory).

11. Add a method that calculates the total price of the calls in the call history. Assume the price per minute is fixed and is provided as a parameter.

ОБЯСНЕНИЕ:  Comming soon.

12. Write a class GSMCallHistoryTest to test the call history functionality of the GSM class.

– Create an instance of the GSM class.
– Add few calls.
– Display the information about the calls.
– Assuming that the price per minute is 0.37 calculate and print the total price of the calls in the history.
– Remove the longest call from the history and calculate the total price again.
– Finally clear the call history and print it.

ОБЯСНЕНИЕ:  Comming soon.

Кодът към всяка една от задачите можете да видите тук.

Telerik C# Part2 Homeworks – Using Classes and Objects (Използване на класове и обекти)

CSharpYodaОбяснение на задачите/упражненията от домашното за Използване на класове и обекти в Академията. Сравнително лесни задачи, в сравнение с предишните, но все пак много важни за разбиране и усвояване, тъй като тази тема е, така да се каже, нещо като леки първи въвеждащи стъпки към същината на Обектно ориентираното програмиране. Надявам се решенията на задачите да са ви полезни. Можете да коментирате всичко, което ви вълнува по тях.

{ Кодът с решенията към всяка една от задачите можете да видите тук }

1. Write a program that reads a year from the console and checks whether it is a leap. Use DateTime.

ОБЯСНЕНИЕ: В тази задача най-лесно е да изпробваме специално предвидения в .NET за целта системен клас DateTime.IsLeapYear, който е предвиден да връща булев резултат, в зависимост от който изписваме на кознозолата, дали годината е високосна или не.

2. Write a program that generates and prints to the console 10 random values in the range [100, 200].

ОБЯСНЕНИЕ: Използваме системния клас Random и неговия метод .Next за да кенерираме 10-те случайни числа. Тъй като Random.Next има една особеност, в следстиве на която, ако му зададем параметри (100, 200), то тогава той би дал числа в интервала 100-199, за да получим 10-те произволни числа в интервала от 100 до 200 трябва да му зададем параметри (100, 201).

3. Write a program that prints to the console which day of the week is today. Use System.DateTime.

ОБЯСНЕНИЕ: Задача, чиято цел е да упражним още един от системните класове на .NET – този път това е System.DateTime.

4. Write methods that calculate the surface of a triangle by given: side and an altitude to it; Three sides; Two sides and an angle between them. Use System.Math.

ОБЯСНЕНИЕ: Откровено казано, малко досадна задача, тъй като ще се наложи да си припомняте навярно доста позабравени от училищните години формули. В общи линии от нас се изисква да изчислим лицето на триъгълник според три различни случая:

1. при дадена страна и височина;
2. при три дадени страни;
3. при две страни и ъгъл между тях.
Sluchai-Formuli
За първия случай ще използваме следната формула: S = (a * h) / 2
За втория случай използваме т.нар. Херонова формула.
При Хероновата формула е важно да бъде изпълнено следното условие: a + b > c.
За третия случай използваме Math.sin като за него ъгълът трябва да е в радиани.
Умножаваме го по Пи и го разделяме на 180.

5. Write a method that calculates the number of workdays between today and given date, passed as parameter. Consider that workdays are all days from Monday to Friday except a fixed list of public holidays specified preliminary as array.

ОБЯСНЕНИЕ: Comming soon.

6. You are given a sequence of positive integer values written into a string, separated by spaces.Write a function that reads these values from given string and calculates their sum. Example:string = „43 68 9 23 318“ –> result = 461

ОБЯСНЕНИЕ: Имаме стринг от числа, разделени помежду си от спейсове и трябва да съберем тези числа. Ползваме input.Split(‘ ‘), за да разцепим стринга по интервалите му, след което, с помощта на един foreach цикъл, прилагаме за всеки един разцепен елемент int.Parse() и накрая просто събираме сумата им.

Кодът към всяка една от задачите можете да видите тук.