Loading...
ttitto avatar ttitto 1153 Точки

[Homework] OOP - Static Members - Септември 2014

Ето и домашното от втората тема:

 

Paths  Понеже първите три задачи са свързани съм ги направил в един проект. Индексаторът при Path3D класът може да се избегне и да се работи през списъка Paths, но исках да го упражня

Geometry (Namespaces) - малко скучна задача, която се решава само с два шорткъта на VS: десен бутон->d->d върху бащината папка в solution explorer (създава нова папка в избраната) и другия шорткът alt+shift+c -създава нов клас в текущата папка, като namespace-a се взима от структурата на директориите

BitArray - Много интересна задача! Тънкостта е да се прецени какъв числов тип да се използва при превръщането на BitArray в число.

HTML Dispatcher - Привидно лесна задача, но като се стигне до overload на операторите става ужас. Как да се овърлодне оператора така че да важи за класа ElementBuilder и същевременно да се получава умножения стринг на елемента? Справих се чрез implicit conversion operator Ще ми е интересно да видя и други решения.

 

13
C# OOP Basics 19/09/2014 21:55:49
Samuil.Petrow avatar Samuil.Petrow 1550 Точки

Решението е ок, като препоръка мога да ти дам да ползваш интерфейси за работа с колекции.

Пример: 

private List<Point3D> paths

може да се замени с

private IEnumerable<Point3D> paths;

или пък

private ICollection<Point3D> paths;

или пък

private IList<Point3D> paths;

 

Взависимост колко искаш да ти е дигната абстракцията. Повече инфо - цък.

 

public Path3D(params Point3D[] points3D)

{

      this.Paths = new List<Point3D>();

      foreach (var point in points3D)

      {

             this.Paths.Add(point);

       }

}

 

Този foreach според мен не е нужен, можеш да подадеш в конструктора на List-a самият array или да дадеш на array-а .ToList() (Тук може да се наложат каствания преди това)

3
18/09/2014 17:15:42
ttitto avatar ttitto 1153 Точки

Много добър аргумент за foreach-a! Благодаря!

За интерфейсите също съм съгласен и обикновено ги ползвам, като се двоумя дали да ползвам IList или IEnumerable, но този път май не се сетих (писах ги на работа и ме разсейваха редовно). Статията изглежда перфектна!

0
oconne avatar oconne 113 Точки

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

За HTML-A ми е подобна тактиката както при теб, но ми се струва че няма смисъл от Closing Tags and Opening Tags, аз това съм го предоставил на класът сам да си го добавя. Eто много сбита и кратка версия на моето домашно (не съм го редактирал, т.е има неща за доимплементиране): Домашно

1
20/09/2014 01:29:42
ttitto avatar ttitto 1153 Точки

Беше ми малко трудно да разбера какво имаш предвид за Size. Специално за целта изгледах лекцията на Наков, но по темата имаше само няколко думи около мин. 8:00. Може би него си имал предвид.

Понеже размера на BitArray се подава като параметър на масива, то вътре в конструктора трябва да се присвоява или директно на полето size, или да се направи свойство Size. Аз предпочитам втория начин, защото може да се направи валидация. Така че наличието на свойство Size e по-скоро оправдано. Единственото, което наистина мисля, че е правилно да променя е достъпът до сетера на свойството Size (направих го private). Потребителят наистина не е редно да има право да променя размера на масива, защото може да се получи разминаване между this.size и размера на this.arr. Благодаря, че ми обърна внимание за това!

По твоето домашно:

В stackoverflow ми беше попаднал по друг повод коментар, че е за предпочитаме да се хвърля ArgumentNullException вместо NullReferenceException. Не задълбочих тогава за причините.

Point3D: струва ми се крайно излишно вкарването на втори метод (toDataPoint) за изписването на точката като стринг.

BitArray: както си го направил, масивът ти винаги ще е с пълен размер, разхищение на ресурси. Ако ползваш инт мисля, че е по-добре да имаш предвид, че един инт е 32 бита и да работиш поотделно с всеки бит. Така максимално масивът ти ще съдържа 100000/32=3125 елемента.

Трудно ми е да коментирам домашното ти повече, защото е едва започнато. Опитвай да ползваш имената на класовете от заданието! На този етап форматирането на кода не е никак добро и продължаваш да слагаш подчертавки. Много ми се иска да видя завършения ти HTML Dispatcher, особено тестове за припокрития оператор *.

1
oconne avatar oconne 113 Точки

Мерси за коментара ти, свърши ми много полезна работа. Диспачера съм го направил , разменил съм обаче местата на класа ElementBuilder и DispatcherHTML, sorry за което. Предефенираният оператор съм го показал в програмс (като че ли) :) .Ти имаш предвид имплицитният оператор, сега видях, не съм го правил защото сметнах че няма нужда (ще го погледна днес по късно). За ексепшаните мисля че си прав, по прецизно е. 

Да точно за тази част от лекцията, Наков много набързо го спомена.

За BitArray нарочно оставих масивът да съхранява 32 битови блокове, а не типът Bool. Направих си някви тестове с всички възможни варянти, включително със Size полето (твоят метод работи най-бързо). На око се вижда че разликата  между int и bool е много малко в полза на bool , което ме втрещи, но май е логично. (очаквах разликата да е огромна )Незнам не съм задълбавал...Иначе е разхищение на памет, определено.   

0
21/09/2014 13:18:00
Valleri avatar Valleri 304 Точки

Ето едно домашно и от мен с цел, да получа feedback : Homework

2
bsdemon avatar bsdemon 348 Точки

Колега, за качеството не мога да кометирам, ама 2-рата задача класа Point, декларираш double x,y,z а в конструктора подаваш int x,y,z.

2
ttitto avatar ttitto 1153 Точки

Първо имам няколко препоръки по качването на кода в гитхъб. Не е добре да се качват bin и obj папките в репозиторито. Има един тоол CleanProject (и във форума е писано за него), който ти почиства папките от ненужни неща, преди да ги качваш в GitHub или да ги пращаш на някого.
sln файла би ми спестил доста време при проверката, ако беше качен
BitArray проектът ми гърми,защото ми казва, че BitArray класът не е включен в проекта. И на мен ми се видя странно, но вероятно нещо не е наред с начина, по който създаваш проектите и добавяш items към тях. Или преди да качиш си затрил някои файлове на VS, които държат информация за solutiona.

HTML Dispatch: Забележките ми тук не са към ООП-то, а към HTML. В HTML няма такива тагове, каквито твоят диспечер създава - <image>, <URL> не съществуват. има таг <img>.
При createImage метода, title е също атрибут, а ти го подаваш като контент.
При createURL май единственото правилно е, че добавяш текста като контент. Според мен задачата изисква да се направи <a> елемент с атрибути href и title, като на href стойността е url.
При createInput() не използваш атрибута typе.
И трите елемента, които диспечерът трябва да създаде се затварят само с ">" или "/>"(преди HTML5), а не с </tagName>
За какво ти е GetAllTags? - предполагам си имал идея да валидираш с него подадения таг, но не го ползваш никъде в момента.

Бях останал с впечатлението, че при припокриване на оператор, трябва да се връща обект от същия клас, и затова в моето решение минах през implicit conversion. Благодарение на твоето домашно ми се изясни това, за което благодаря!

1
RoYaL avatar RoYaL Trainer 6849 Точки

Според мен за правилен OO way отделните тагове трябва да са отделни класове, или поне различните - тези които се затварят по различен начин като Input и Image.

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

2
nickpanaiotov avatar nickpanaiotov 21 Точки

Имам един глупав въпрос, защо ни трябва DistanceCalculator-a и Path да са два отделни класа? Не е ли по логично да са методи на Point? Има ли смисъл да съществува път без точки?  

0
oconne avatar oconne 113 Точки

Разбира се че калсът Path mоже да държи тези методи. Методите са отделени в друг клас, защото когато приложението се усложни доста, тяхното присъствие сигурно черпи ресурс а и кода става не приятен за разбиране. Добре е нещата да са гранулирани максимално (задачите да се разпределят по всевъзможните там конструкции на кода). По просто казано е Функции да се държат извън класа, а мутатори, модификатори, "конструкторни" методи и бихейвористични методи да си ги пази самият клас. 

Винаги има смисъл да зададеш празно състояние на класа, не NULL а нулирано със сътветните нули, защото повечето алгоритми са индуктивни и когато правят итерации или сатртират от нулата или отиват към нея неизбежно. Нещо такова ми е отговора.

0
21/09/2014 13:44:28
apelev avatar apelev 16 Точки

На първа задача, като създадем startingPoint, който да бъде от тип Point3D със статичния конструктор, при мен в дебъгера се получава едно безкрайно създаване на тая статична променлива startingPoint. Понеже не мога да го обясня. Ето го моя код и скрийншот от дебъгера. Някой, ако има представа, да каже, как да го избегнем това. Или пък аз съм в грешка?

 

http://pastebin.com/2SjnMFd3

 

point3d

0
21/09/2014 20:19:32
ttitto avatar ttitto 1153 Точки

По кода всичко ти е почти наред, само малко разхвърляно тук конструктор, там конструктор. Направи свойството StartingPoint статично и в него достъпвай полето с Point3D.startingPoint.

Нали знаеш, че статичните конструктори не е необходимо да се викат изрично. Те се стартират автоматично, щом класът ти влезе в употреба. От друга страна и двата ти конструктора могат да се извикат без да им се подават аргументи. Как според теб ще е ясно кой от двата да се извика? Не виждам причина да имаш нули по подразбиране там - каква е идеята ти зад това?

0
21/09/2014 21:09:58
ZvetanIG avatar ZvetanIG 907 Точки

Ето и моето домашно. И аз съм събрал 1, 2 и 3 задача в едно - просто си плачат за това.

1. Point3D
2. Distance Calculature
3. Path
4. HTMLDispatcher
5. BitArray
6. Namespaces

Тъй като, вече започнахме и  КПК, ще си  позволя да посоча като забележка на вече качените домашни, това, че не се затриват излишния код, който автоматично се генерират от VS. Счита се за лоша практика (дори грешно) да се оставят неща, които не се използват.

6
22/09/2014 11:47:40
Vasilsk avatar Vasilsk 109 Точки

Здравей Цецо,

Имам въпрос относно решението ти на Point.cs. Защо в конструктора ти public Point(double x, double y, double z) имаш this.x = x;, а не е this.X = x; ?

Доколкото разбрах от лекцията, конструктора се прави, за да може чрез него да се пипат стойностите на иначе недостъпния извън класа параметър(бидейки private static). И след това на този конструктор се прави пропърти, където може да задаваме разни ограничения и да хвърляме ексепшъни ако ни подават невалидна информация. Съответно си мислех, че в конструктора трябва да имаме this.(Името на пропъртито) = името на променливата(с малка буква). Поправи ме ако греша някъде, моля :)

2
22/09/2014 19:54:26
ZvetanIG avatar ZvetanIG 907 Точки

Здрасти Васко,

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

А относно this.x = x.  this.x е поле на класа, а x e параметър на конструктора. За да ти стане по-ясно ще го напиша по следния начин.

 

public Point(double PointX, double PointY, double PointZ)
{
this.x = PointX;
this.y = PointY;
this.z = PointZ;
}

 

Ами това е. Дано съм разбрал правилно въпроса ти.

6
Vasilsk avatar Vasilsk 109 Точки

Ясно, сега го разбрах, благодаря ти много smile

0
n.galabov avatar n.galabov 40 Точки

Колеги, при overload на оператори как да постигнем code reusability? В задачата с HTML Dispatcher пиша един и същи код с 2 различни параметъра, а съм сигурен, че има начин да се избегне. Благодаря ви!

0
22/09/2014 18:22:33
ttitto avatar ttitto 1153 Точки

Не ти разбрах въпроса?! Дай пример с код какво и къде повтаряш!

0
n.galabov avatar n.galabov 40 Точки

Става въпрос за "умножение" на div с число. Искам кодът да работи и при умножение на число с div 

Пример http://pastebin.com/rbjqBWYE

0
22/09/2014 20:06:22
ttitto avatar ttitto 1153 Точки

Първото, което се сещам е да си направиш private метод с повтарящото се съдържание и да го викаш от двата "оператора"

Второто, което ми хрумва е да направиш generic методите за презаписване на операторите, като вътре в тях проверяваш кой от двата предоставени аргумента е от тип ElementBuilder и  кой от тип int и си ги обработваш както искаш.

Това второто предложение не съм го тествал, така че незнам дали ще стане. Само теоретични размисли...Сигурно утре ще имам време да го пробвам и ако стане ще ти пиша тук.

1
Karlie avatar Karlie 438 Точки

Моля за малко помощ. Второто домашно го докарах дотук: OOP_HW2. В момента задача едно и две ми работят, когато са в един проект. Както се вижда, първоначално опитах да сложа задача 2 в отделен проект в същия solution, но не мога да си дефинирам 3д точка, въпреки, че класът ми Point3D е public. Пробвах да включа namespace-a на първата ми задача във втората, не го вижда. Какво пропускам и защо не мога да си дефинирам 3д точка в отделен проект? yell

Благодаря!

0
Karlie avatar Karlie 438 Точки

Стана, много благодаря!

0
Dzhuliya avatar Dzhuliya 5 Точки

Аз също имам подобен проблем. Добавих референцията към solution-а с 3d точката. Всичко беше точно до момента, в който не се опитвам да използвам конструктора за създаване на точка. Получавам следните грешки:
Error1 Inconsistent accessibility: parameter type 'Problem_1.Point3D.Point3D' is less accessible than method 'Problem_2.Distance_Calculator.DistanceCalculator.CalcDistance(Problem_1.Point3D.Point3D, Problem_1.Point3D.Point3D)

Error3 'Problem_1.Point3D.Point3D' is inaccessible due to its protection level

И за двете точки получавам тези грешки. Не мога да разбера къде е проблема, при положение, че конструктора ми е публичен, направила съм си достъп с пропъртита, имам референция към класа, пък не работи. Ето и кода на първа и втора задача, тъй като там ми е класа за правене на точка. Благодаря предварително!

 

0
23/09/2014 13:18:49
vladislav_hadzhiyski avatar vladislav_hadzhiyski 66 Точки

Здравейте,

Реших да споделя какво измъдрих относно задачата BitArray. Реших я като сам си написах един BigInteger.

Решение

1
yavor2000 avatar yavor2000 114 Точки

Браво колега! И аз обичам да "пренаписвам топлата вода", т.е. да си пиша сам методи, които имаче ги има (като BigInteger).

Не съм направил цял нов BigInteger клас, но си измислих събирането на огромни числа и повдигането 2 на степен до 100 000.

Ето моето решение BitArray

п.п. пробвах твоето решение с 100-хилядния бит сетнат на 1, което трябва да върне десетично число с над 30000 цифри, но след 10 минути работа още няма резултат. Моето решение се справя с 10-хиляден бит за 1.26 сек, а с 100-хилядния за почти 2 минути. За сравнение .NETския BigInteger се справя за стотни :)

1
vladislav_hadzhiyski avatar vladislav_hadzhiyski 66 Точки

Поздравления за решението. Моето има нужда от доста оптимизации защото като цяло събирането на числа върви бавно а умножението разчита на събирането laughing и като искаш да ти събере число с 30000 цифри с някакво друго и увисва.

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