Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/64: Рейтинг темы: голосов - 64, средняя оценка - 4.80
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

Абстрактные классы и интерфейсы. Разница

01.09.2017, 18:35. Показов 13407. Ответов 30
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот хоть убейте, не могу понять разницы между абстрактным классом и интерфейсом. До этого изучал C++, там не было интерфейсов, скорее всего из-за этого проблемы моего непонимания...
Нет, я понимаю, что в абстрактном классе могут быть методы, которые имеют реализацию, но хоть один метод должен быть абстрактным, напротив в интерфейсах все методы должны быть чистым протоколом...
В этом чтоли только различие? Ну не делай ты в абстрактном классе методов с реализацией и все, что его будет отличать от интерфейса?
Или интерфейсы сделаны для того, чтобы можно было реализовывать "неполное" множественное наследование? Ну так не запрещали бы множественного наследования...

Какие еще различия есть? Пока я не увидел глобальной разницы...
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.09.2017, 18:35
Ответы с готовыми решениями:

Абстрактные классы и интерфейсы
Добрый день, какой смысл в C# был заложен в создание интерфейсов, а не использование абстрактных классов. Да я знаю отличия, что в...

Интерфейсы и абстрактные классы
Всем привет! Помогите пожалуйста, недавно подкинули вопрос, который заинтересовал: что было бы если разработчики Майкрософт Icomparable...

Интерфейсы и абстрактные классы: каково их назначение
Прошу объяснить: зачем нужны эти объекты? Неужели нет таких ситуаций, где без них не обойтись? Вот например: интерфейсы могут быть...

30
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
02.09.2017, 11:20
Студворк — интернет-сервис помощи студентам
Bretbas, так ты не используешь интерфейс, замени 24ю строку на IMyInteface ai = new AInterface();
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
02.09.2017, 11:26  [ТС]
Aael, заменил
C#
1
2
AInterface ai = new AInterface();
AClass ac = new AClass();
на
C#
1
2
IMyInteface ai = new AInterface();
AbstractClass ac = new AClass();
тоесть вызов метода произвожу через интерфейс, и через базовый абстрактный класс. Все равно вывод в пользу интерфейсов:
C#
1
2
Invoke interface method: 00:00:22.6063000
Invoke abstract class method: 00:00:23.5609688
0
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
02.09.2017, 11:34
Bretbas, та ты что-то не так с тестом делаешь, вот твой тест 5 раз подряд:
Кликните здесь для просмотра всего текста
Invoke interface method: 00:00:05.6080583
Invoke abstract class method: 00:00:03.7198910
Invoke interface method: 00:00:05.5876918
Invoke abstract class method: 00:00:03.7193130
Invoke interface method: 00:00:05.5725993
Invoke abstract class method: 00:00:03.7168229
Invoke interface method: 00:00:05.5751074
Invoke abstract class method: 00:00:03.7229329
Invoke interface method: 00:00:05.5926129
Invoke abstract class method: 00:00:03.7180879

и в обратном порядке:
Кликните здесь для просмотра всего текста
Invoke abstract class method: 00:00:04.3579636
Invoke interface method: 00:00:05.5479269
Invoke abstract class method: 00:00:04.3037285
Invoke interface method: 00:00:05.5326887
Invoke abstract class method: 00:00:04.3118644
Invoke interface method: 00:00:05.5359607
Invoke abstract class method: 00:00:04.3090508
Invoke interface method: 00:00:05.5321756
Invoke abstract class method: 00:00:04.3044105
Invoke interface method: 00:00:05.5290812
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
02.09.2017, 12:01  [ТС]
Aael, что можно с тестом не так делать, тут кода-то с гулькин хрен. Еще раз, вот мой код теста:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
interface IMyInteface
{
    void Method();
}
abstract class AbstractClass
{
    public abstract void Method();
}
class AInterface : IMyInteface
{
    public void Method() {}
}
class AClass : AbstractClass
{
    public override void Method() {}
}
 
class Program
{
    static void Main(string[] args)
    {   
        IMyInteface ai = new AInterface();
        AbstractClass ac = new AClass();
        var sw = new Stopwatch();
 
        for( int j = 0; j < 5; j++ )
        {
            Console.WriteLine( "Test #{0}", j );
 
            sw.Restart();
            for( int i = 0; i < int.MaxValue; i++ )
                ai.Method();
            sw.Stop();
            Console.WriteLine( "Invoke interface method: {0}", sw.Elapsed );
 
            sw.Restart();
            for( int i = 0; i < int.MaxValue; i++ )
                ac.Method();
            sw.Stop();
            Console.WriteLine( "Invoke abstract class method: {0}", sw.Elapsed );
        }
        Console.ReadLine();
    }
}
...
Результат:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Test #0
Invoke interface method: 00:00:24.2334683
Invoke abstract class method: 00:00:29.9179415
Test #1
Invoke interface method: 00:00:22.3460789
Invoke abstract class method: 00:00:30.5036110
Test #2
Invoke interface method: 00:00:20.6650564
Invoke abstract class method: 00:00:27.6195824
Test #3
Invoke interface method: 00:00:22.4426222
Invoke abstract class method: 00:00:29.1450178
Test #4
Invoke interface method: 00:00:21.8823905
Invoke abstract class method: 00:00:29.4373637
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
02.09.2017, 12:03
Мда, понимать бы еще все это...
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
mi1.Method1();
mov    ecx,edi                 ; поместить указатель this в ECX
mov    eax,dword ptr [ecx]     ; поместить TypeHandle в EAX
mov    eax,dword ptr [eax+0Ch] ; поместить адрес IVMap
                               ; (смещение 12) в EAX
mov    eax,dword ptr [eax+30h] ; поместить начальный слот 
                               ; реализации интерфейса в EAX
call   dword ptr [eax]         ; вызов метода
 
mc.Method1();
mov    ecx,esi                 ; поместить указатель this в ECX
cmp    dword ptr [ecx],ecx     ; сравнение и установка флагов
call   dword ptr ds:[009552D8h]; прямой вызов Method1
Как видно из этого дизассемблированного кода, при прямом вызове методов экземпляра MyClass смещение не используется. JIT-компилятор записывает адрес MethodDesc прямо в код. При диспетчеризации на основе интерфейсов используется IVMap и выполняется несколько больше инструкций, чем при прямой диспетчеризации. Одна инструкция получает адрес IVMap, другая — начальный слот реализации интерфейса, содержащийся в Method SlotTable. При приведении экземпляра объекта к интерфейсу этот указатель просто копируется в нужную переменную.
Осталось понять, почему это так плохо.

Цитата Сообщение от Aael Посмотреть сообщение
Кстати, есть такойже тест как у вас (здесь) где документально подтверждено, что интерфейсы медленнее.
лол, 1 наносекунда на 100кк итераций.
Цитата Сообщение от Aael Посмотреть сообщение
дает существенный повод для оптимизации с отказом от использования интрефейсов (сарказм).
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
02.09.2017, 12:10  [ТС]
Wolfdp, Что скажете о моем тесте? Почему же у меня вызов интерфейсного метода быстрее чем вызов абстрактного, если на вызов интерфейсного уходит больше инструкций процессора?
0
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
02.09.2017, 12:27
Цитата Сообщение от Wolfdp Посмотреть сообщение
лол, 1 наносекунда на 100кк итераций.
факт в том, что в с++ таких проблем нет, возвращаясь к вопросу тс, получается, что в .net наплодили лишних сущностей и реализаций с сомнительными выгодами, а "по-старому" писать не дают.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
02.09.2017, 12:58  [ТС]
Aael,
Цитата Сообщение от Aael Посмотреть сообщение
получается, что в .net наплодили лишних сущностей и реализаций с сомнительными выгодами, а "по-старому" писать не дают.
Я сейчас изучаю C#. Читаю книгу Андрю Троелсена. При прочтении стараюсь сразу сравнивать с C++ естественно. Из-за этого и не понятки возникают.

Вот к примеру еще один момент. К примеру есть класс, который реализует IEnumerable, чтобы использовать этот класс в конструкциях foreach для внутреннего массива этого класса. Как лучше реализовать GetEnumerator()? Троелсен предлагает с помощью делегирования внутренного класса внешнему вызову:
C#
1
2
3
4
5
6
7
8
9
10
class Car {}
class Garage : IEnumerable
{
    Car[] cars = new Car[10];
    
    IEnumerator GetEnumerator()
    {
        return cars.GetEnumerator();
    }
}
Есть еще способ с ключевым словом yield, которое как я понял, может при каких-либо циклических операциях начинать с того места, с которого мы закончили, не начиная цикл заново:
C#
1
2
3
4
5
6
7
8
9
10
11
class Car {}
class Garage : IEnumerable
{
    Car[] cars = new Car[10];
    
    IEnumerator GetEnumerator()
    {
        foreach( var car in cars )
            yield return car;
    }
}
И то, и то работает. Вот сравнил по времени:
C#
1
2
3
4
5
6
7
8
9
10
return cars.GetEnumerator(): 00:00:00.1210650
yield return car: 00:00:00.0512750
return cars.GetEnumerator(): 00:00:00.0582386
yield return car: 00:00:00.0472201
return cars.GetEnumerator(): 00:00:00.0624685
yield return car: 00:00:00.0431251
return cars.GetEnumerator(): 00:00:00.0574090
yield return car: 00:00:00.0423058
return cars.GetEnumerator(): 00:00:00.0594734
yield return car: 00:00:00.0410783
Почему yield работает быстрее? Есть смысл тогда в делегировании в данном случае?
0
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
02.09.2017, 13:12
Bretbas, видимо опять что-то с тестами т.к. по логике (здесь я могу ошибаться с тем как это работает в массивах) вы просто делаете лишние действия:
C#
1
2
3
4
5
IEnumerator GetEnumerator()
    {
        foreach( var car in cars ) // в этом месте for будет просматривать cars.GetEnumerator();
            yield return car;
    }
т.е. это вобще разные вещи, если есть возможность делегировать - то нужно делегировать. yield это всего лишь конструкция для создания нового итератора (enumerable), в случае с массивами он уже есть готовый. А вот если нужно вместо car вернуть foo(car) то без
C#
1
foreach(var car in cars) yield return foo(car);
не обойтись (явным или неявным способом).
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
02.09.2017, 13:21  [ТС]
Aael,
Цитата Сообщение от Aael Посмотреть сообщение
т.е. это вобще разные вещи, если есть возможность делегировать - то нужно делегировать. yield это всего лишь конструкция для создания нового итератора (enumerable), в случае с массивами он уже есть готовый.
Вот и мне стало непонятно, почему с yield у меня быстрее. С тестами все нормально, что с ними может быть не так?
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
02.09.2017, 13:31
Цитата Сообщение от Bretbas Посмотреть сообщение
Что скажете о моем тесте?
спрашивайте у винды, как она распределяет процесорное время. Вообще такой тест нужно запускать на чистой винде, с отключеным антивирусом, не из под дэбага и отсутствием любых сервисов и запущеных оных програм.

Цитата Сообщение от Aael Посмотреть сообщение
что в .net наплодили лишних сущностей и реализаций с сомнительными выгодами
Унификация и упрощение кода. Вообще .net больше для бизнес решений, тут интерфейсы/базовые попутно упрощают понимание происходящего.

Добавлено через 3 минуты
Цитата Сообщение от Aael Посмотреть сообщение
не обойтись (явным или неявным способом).
для конкретного примера придумали Linq.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.09.2017, 13:31

Интерфейсы и абстрактные классы: обеспечить работу методов в конечном классе
Имеются два шаблонных интерфейса, в которых описан метод Print() От этих двух интерфейсов наследуется шаблонный абстрактный класс в...

Абстрактные классы
Здравствуйте. Задача следующая. У меня есть огромное количество форм с частью одинакового функционала, и нужно смастерить базовую...

абстрактные классы
помогите пожалуийстаб не доет правильный ответ, не могу найти ошибку. Спасибо abstract class Shape { protected double...

Абстрактные классы
Всем привет! Вопрос такой: Есть абстрактный класс, а в нем абстрактный метод, который должен заменять значения свойств и полей класса....

Интерфейс и абстрактные классы
После прочтения Хабро-статьи http://habrahabr.ru/post/169949/, после коммента: &quot;Стандартные вопросы тоже не стоит оставлять без внимания....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
Новые блоги и статьи
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Реализация из решения ниже выполнена в самописной конфигурации на БСП (помощь начинающему коллеге). Задача: Программно добавить префикс в нумерацию документов. Решение: В модуле объекта. . .
После закрытия оутлука продолжает висеть процесс в диспетчере задач
Maks 27.10.2026
С недавнего времени в продакшене возникла проблема: при закрытии оутлука в диспетчере задач продолжал висеть процесс outlook. exe. Проблема возникла после установки MS Office 2021 LTSC на машинах, под. . .
Baragoz - DPS/HPS бот для WoW 3.3.5a, многоязычный
AmbA 26.10.2026
Хотите ещё ботов? У меня есть один! А я пока отдохну от него. https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=12062&stc=1&d=1793007952 Инструкция внутри. https:/ / youtu. be/ VpfFZSUDGnQ. . .
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru