Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Абстрактный класс и виртуальный метод


Автор: 666TEHb666 22.11.2010, 00:33
Здравствйте.

Недавно задавал вопрос по интерфейсу. Мне помогли и вопрос был решен. Но по ходу написания других классов библиотеки появился еще один вопрос. В принципе, все работает, но я не могу понять как. Очевидно теорию я слабо копал или просто запутался. Вообщем поясните ситуацию, если не затруднит.
Суть вот в чем:

Есть интерфейс
   
Код

 interface IControl
    {
        //...
        void Draw(SpriteBatch spriteBatch, float imgWidth, float imgHeight);
    }


Его наследует абстрактный класс
Код

abstract public class Control : IControl
    {
        #region свойства
        //...
        #endregion

        #region методы
        public void CreateBackImg(SpriteBatch spriteBatch, float imgWidth, float imgHeight, Vector2 Location)
        {
             //...
        }

        public void Draw(SpriteBatch spriteBatch, float imgWidth, float imgHeight, Vector2 Location)
        {
            CreateBackImg(spriteBatch, imgWidth, imgHeight, Location);
        }
        #endregion
    }


Этот класс дает реализацию сигнатуры интерфейса Draw().

Далее, другой класс наследует абстрактный Control и переопределяет метод Draw().

Код

 public class BasePanel : Control
    {
         //...
         public void Draw(SpriteBatch spriteBatch)
        {
            CreateBackImg(spriteBatch, Constants._BP_backImg_width, Constants._BP_backImg_height, new Vector2(Location.X, Location.Y));
            //...
        }
}


Работать то все это работает. Вызывается нужный переопределенный метод.. Но не совсем пойму почему не надо писать override и virtual. Ну virtual наверное потому что в абстрактном классе и так методы виртуальные..но override тогда почему? Или здесь подразумевается просто новая реализация метода?
Просто запутался немного,буду признателен, если поясните.
Заранее благодарю.

Автор: Экскалупатор 22.11.2010, 00:55
переопределение это новая реализация метода с уже заданной сигнатурой, т.е. ты заменяешь старое тело метода на новое, а ты просто добавил перегрузку метода Draw.

Добавлено через 1 минуту и 39 секунд
к примеру если ты укажешь в абстрактном классе что метод Draw абстрактный то компилятор скажет что твой класс-наследник не реализовал абстрактный метод из класса Control.

Автор: neutrino 22.11.2010, 11:18
Цитата(666TEHb666 @  21.11.2010,  23:33 Найти цитируемый пост)
 void Draw(SpriteBatch spriteBatch, float imgWidth, float imgHeight);


Цитата(666TEHb666 @  21.11.2010,  23:33 Найти цитируемый пост)
public void Draw(SpriteBatch spriteBatch, float imgWidth, float imgHeight, Vector2 Location)


Обрати внимание на сигнатуру (имя, параметры и возвращаемый тип), она отлична от предысущих. 
Цитата(666TEHb666 @  21.11.2010,  23:33 Найти цитируемый пост)
public void Draw(SpriteBatch spriteBatch)

Как правильно сказал Эксплуататор, это просто перегрузка метода. Если бы ты в последнем классе указал метод с той же сигнатурой, компилятор бы ругался и решение было бы объявить в абстрактном классе этот метод виртуальным.

Автор: 666TEHb666 22.11.2010, 20:38
Экскалупатор, neutrino, спасибо за ответы.

Теперь понял. Вот только,чтобы вы посоветовали: оставить как есть перегруженный метод и следить чтобы вызывался именно он или переопределить тот,оставив просто неиспользуемые параметры( чтобы не было возможности вызвать некорректный метод,так как он вроде сохранится тоже,если я правильно понял..)..

Цитата

Обрати внимание на сигнатуру (имя, параметры и возвращаемый тип), она отлична от предысущих.


Да я знаю =) Просто потом уже увидел после того как создал тему,компилятор вежливо напомнил =) Я исправил, расширив сигнатуру интерфейса.

Автор: Экскалупатор 22.11.2010, 21:56
тут все зависит от предполагаемого использования. переопределение не заменяет перегрузки. 
к примеру если у тебя есть класс "фигура"(Shape), с абстрактным методом "рисовать"(Draw). ты делаешь наследников от "фигура" - "круг", "квадрат", "ромб", каждый из которых по своему реализует метод "рисовать". так вот ты можешь создать массив классов "фигура", потом заполнить его разными наследниками класса фигура(кругами, квадратами и пр.), то ты сможешь обходить массив фигур вызывая по индексу для каждого элемента метод Draw, и у тебя каждый раз будет вызываться нужная перегрузка метода.(т.е. если пятый элемент круг то вызовется метод для круга, если квадрат то для квадрата). с перегрузкой этого сделать не получится. так что отталкивайся от своей архитектуры.

Автор: neutrino 23.11.2010, 09:53
Цитата(Экскалупатор @  22.11.2010,  20:56 Найти цитируемый пост)
 у тебя каждый раз будет вызываться нужная перегрузка метода.

Будет вызываться нужная реализация.

Автор: Экскалупатор 23.11.2010, 14:05
 smile 
neutrino, точно. что то я в последнее время слова забываю. к чему бы это по хаусу? к волчанке? или все же печень отказывает? надо сделать полный диализ...

Автор: 666TEHb666 24.11.2010, 18:12
neutrino, Экскалупатор

Еще раз благодарю за ответы и участие =) Учту свою архитектуру и, думаю, оставлю перегрузку, а в первичной реализации выброшу исключение.
Вопрос решен.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)