Професионална програма
Loading...
+ Нов въпрос
sevdalin avatar sevdalin 38 Точки

Override CompareTo, Sort() - Обяснение и пример

Здравейте, някой може ли да обясни как става override на метод, не само на CompareTo. Можем ли да направим клас, който да наследява само определен метод и след това да го Override или не? Как по-точно става override-ването, като напишем пример:

public override string ToString()

{

}

Има ли други начини и как би изглеждало за CompareTo? Конкретно ме интересува как можем да си пишем custom CompareTo за да сравняваме обекти. Същото важи и за метода Sort(), как можем да си напишем клас, който прави сортиране на обектите по-начин по-който ние желаем и после да използваме този клас за да сортира нашите обекти?

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

Благодаря.

Тагове:
0
C# OOP Basics 02/06/2017 09:43:27
Sim0o0na avatar Sim0o0na Trainer 567 Точки

Здравей,

overriding-a е свойството да "презаписваш" методи в класове, които наследяват тези методи в някаква йерархия, т.е всеки базов клас, който "показва" методите си на своите класове-деца, предразполага към това тези деца да override-нат тези методи и да ги използват за техните нужди.

  1. "Можем ли да направим клас, който да наследява само определен метод и след това да го Override или не?" - прочети добре за access specifiers - private, protected, public и ще успееш сам да си направиш извода по какъв начин можеш да наследяваш само един метод.
  2. "Как по-точно става override-ването, като напишем пример toString()?" - презаписват се само методи, които са от един и същи return type, имат еднакъв access modifier и имат едно и също име, което значи, че при използването на наследения метод toString() например, чрез override ключовата дума ти казваш, че имплементацията, която си заложил в него, е тази, която ще се използва.
    Например, ако имаш клас Human и неговия toString() метод казва, че ще го представи като "Name: ${името}, Years: ${години}", класът Child, който го наследява, може да override-не този метод и да получиш "Name: ${името}, Years: ${години}, School: ${училището}", където училището е поле, което само Child класът има. По този начин "нагаждаш" метода да работи подходящо за класа, който имплементираш.
  3. Конкретно ме интересува как можем да си пишем custom CompareTo, за да сравняваме обекти - проучи писането на custom comparer класове, конкретно наследяването на IComparer и Compare метода, който можеш да подаваш при sort функции. Например:
    class <strong>CustomComparator</strong> : <strong>IComparer</strong><string>{
        public int <strong>Compare</strong>(string x, string y){
            //логика за сравняване
            <strong>return x.CompareTo(y);</strong>
        }
    }
    var example = new List<string> { "c", "b", "a", "d", "foo", "", "1", "e"};
    <strong>example.Sort(new CustomComparator());</strong>

 Надявам се съм ти дала малко повече конкретика върху какво да се концентрираш да прочетеш. Съветвам те да изгледаш и видеа от предни инстанции на курса, дори и от Java професията.

Успех

2
02/06/2017 13:42:25
RoYaL avatar RoYaL Trainer 6847 Точки

Тук има една основна концепция, която трябва да разбереш при обектно-ориентираното програмиране, а именно - наследяване.

За да презапишеш метод (override) трябва този метод да идва от твой родител. Идеята тук е, че всички обекти от този тип имат съответното действие, но различните типове извършват това действие по различен начин. Например действието "писане" се извършва по раличен начин от "принтер", "пишеща машина" и "химикал".

За да обобщиш, че "принтер", "пишеща машина" и "химикал" имат действието "писане" и да ги третираш като едно (многоформие, полиморфизъм), трябва да наследят един общ родител, който ще кръстим "писач".

"Писачът" е друг клас, който има действието "писане" и го извършва (или не го извършва - бива абстрактен, но това е друга тема) по някакъв начин. Неговите наследници презаписват това действие и го извършват по друг начин.

class Writer
{
    public void Write() { Console.WriteLine("Default Write"); }
}

Съответно аналогия на по-горното нещо с ToString() в конкретния случай, би било:

class Printer : Writer
{
    public override void Write() { Console.WriteLine("I do print on a paper !"); }
}

Сега може би забелязваш това двуеточие след "Printer". Този оператор нотира, че се извършва наследяване. Чете се "Принтер наследява Писач". Само когато наследяваш даден клас (или интерфейс, там терминът е "имплементиране", но отново се извършва с двуеточие и не е обект на текущия отговор), можеш да презаписваш методи.

За да презапишеш CompareTo() метода, трябва да наследиш клас/интерфейс, който има такъв метод. В противен случай, няма какво да презаписваш. Те първа създаваш такова поведение. Лошото е, че ако просто го създаваш поведението, класът ти няма да работи с много вградени функционалности, които разчитат на принципите на ООП - абстракция и полиморфизъм. Те ще очакват не просто класа ти да има метод CompareTo, а да е сравним тип. Т.е. да наследява определен клас или интерфейс. Има такъв в стандартната библиотека (.NET Framework) - интерфейсът IComparable ( https://msdn.microsoft.com/en-us/library/system.icomparable.compareto(v=vs.110).aspx ).

В момента, в който твоят клас наследи този интерфейс. ще бъдеш задължен да презапишеш метода по конвенцията на ToString() и на по-горния Write.

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

След всичко това се чудиш може би, защо е нужно да наследяваме класове или интерфейси, за да презаписваме методи, при положение че ToString() можем да го презапишем и без да наследяваме нищоБ Всъщност това твърдение не е вярно.

Има един клас Object, в който се намира метода ToString(). Всички класове, които пишеш, без значение дали наследяват нещо или не, те по дефиниция наследяват Object. Представи си, че "class Printer" е същото като "class Printer : Object".

 

5
sevdalin avatar sevdalin 38 Точки

Благодаря за отговорите! :)

0