Re[5]: Breaking change
От: _NN_ www.nemerleweb.com
Дата: 12.12.22 17:12
Оценка: +3 -1
Здравствуйте, Baiker, Вы писали:

Q>>Основная мотивация, стоящая за default interface methods — чтобы можно было добавлять методы в интерфейс, не ломая компиляцию существующих имплементоров.


B>Хм... а это что за идиотизм?? С чего бы это изменённый предок "не должен" ломать наследников? ЕЩЁ КАК ДОЛЖЕН!!

B>Если у тебя класс "ГеомФигура" и ты помимо "Площадь" добавил метод "Периметр", все наследники обязаны реализовать правильный метод "Периметр"!
B>Собственно, потому интерфейс и является КОНТРАКТОМ, что там нет "отлынивающих классов" — любой из наследников ОБЯЗАН корректно реализовать контракт.

Когда у вас будет библиотека хотя бы с сотней тысяч пользователей, попробуйте поломать базовый интерфейс.
А если счёт идёт на миллионы строк кода как в интерфейсах .NET?

Представьте, например, что у вас есть большой проект где каждая команда отвечает за свою часть продукта.
Теперь, вы меняете базовый интерфейс, нужно поменять код во всех частях проекта, а для этого придётся ещё и получить одобрение на изменение от всех команд.

Эта функциональность позволяет решить конкретную проблему с наименьшими проблемами.
Если вам нужно, чтобы можно было вызывать без приведения к интерфейсу, используйте класс.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: Breaking change
От: Doc Россия http://andrey.moveax.ru
Дата: 13.12.22 02:10
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Представьте, например, что у вас есть большой проект где каждая команда отвечает за свою часть продукта.

_NN>Теперь, вы меняете базовый интерфейс, нужно поменять код во всех частях проекта, а для этого придётся ещё и получить одобрение на изменение от всех команд.

Ну да, а так по тихому поменяли контракт. Правда у нас теперь "Периметр()" круга равен "Периметр()" квадрата (возвращаясь к примеру выше), но это мелочи, ведь билд не ломается.

Плюс, теперь можно валить на собесах вопросом "чем отличается интерфейс от класса"
Re[7]: Breaking change
От: _NN_ www.nemerleweb.com
Дата: 13.12.22 06:45
Оценка: +2 -1
Здравствуйте, Doc, Вы писали:

Doc>Здравствуйте, _NN_, Вы писали:


_NN>>Представьте, например, что у вас есть большой проект где каждая команда отвечает за свою часть продукта.

_NN>>Теперь, вы меняете базовый интерфейс, нужно поменять код во всех частях проекта, а для этого придётся ещё и получить одобрение на изменение от всех команд.

Doc>Ну да, а так по тихому поменяли контракт. Правда у нас теперь "Периметр()" круга равен "Периметр()" квадрата (возвращаясь к примеру выше), но это мелочи, ведь билд не ломается.

В каком плане поменяли контракт ?

Вот у нас был код:

public interface IA
{
 void F();
}

static class X
{
 public UseIAF(IA a)
 {
  a.F();
 }
}


class A : IA
{
 public void F() { .. .}
}


Добавляем метод по умолчанию.
Можем использовать G, которого раньше не было.

public interface IA
{
 void F();

 void G() { }
}

static class X
{
 public UseIAF(IA a)
 {
  a.F();
 }

 public UseIAG(IA a)
 {
  a.G();
 }
}


В реализации интерфейса ничего не меняется как и ожидалось.
class A : IA
{
 public void F() { .. .}
}


Какую проблему вы здесь видите ?

Doc>Плюс, теперь можно валить на собесах вопросом "чем отличается интерфейс от класса"


Интерфейс всё ещё остается интерфейсом.
Наследоваться от двух классов нельзя в отличии от реализации множества интерфейсов.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[8]: Breaking change
От: Doc Россия http://andrey.moveax.ru
Дата: 13.12.22 08:52
Оценка: +3
Здравствуйте, _NN_, Вы писали:

_NN>В каком плане поменяли контракт ?

Добавление метода в интерфейс. Это изменение контракта (даже если оно non breaking).

_NN>Какую проблему вы здесь видите ?

В этом теоретическом примере вижу следующие проблемы
— интерфейс более не абстракция.
— интерфейс знает о реализациях, иначе откуда такая уверенность что дефолтный G() подходит для всех реализаций интерфейса.
— если по какой-то причине G() гарантированно подходит для любой реализации, то он может вполне себе быть extension методом.
— программист реализации может просто не заметить добавления G(), который будет не корректный для его реализации. Но в проекте IA.G() рано или поздно кто-то вызовет.

_NN>Интерфейс всё ещё остается интерфейсом.

_NN>Наследоваться от двух классов нельзя в отличии от реализации множества интерфейсов.

Только это не основное свойство интерфейса. Интерфейс в первую очередь это абстракция, а теперь можно затянуть в него реализацию.
Не лучше было бы для таких кейсов ввести что-то типа "abstract base class" который бы и реализовывал такое поведение (по сути ведя себя как интерфейс с дефолтными методами)? А пользователю библиотеки уже выбирать наследоваться от интерфейса или такого класса.
Re[9]: Breaking change
От: karbofos42 Россия  
Дата: 13.12.22 09:55
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>- интерфейс более не абстракция.

Doc>- интерфейс знает о реализациях, иначе откуда такая уверенность что дефолтный G() подходит для всех реализаций интерфейса.
Doc>- если по какой-то причине G() гарантированно подходит для любой реализации, то он может вполне себе быть extension методом.
Doc>- программист реализации может просто не заметить добавления G(), который будет не корректный для его реализации. Но в проекте IA.G() рано или поздно кто-то вызовет.

Все эти проблемы присущи и абстрактному классу, на который ниже предлагается заменить такие интерфейсы

Doc>Только это не основное свойство интерфейса. Интерфейс в первую очередь это абстракция, а теперь можно затянуть в него реализацию.

Doc>Не лучше было бы для таких кейсов ввести что-то типа "abstract base class" который бы и реализовывал такое поведение (по сути ведя себя как интерфейс с дефолтными методами)?

В C# нет множественного наследования, поэтому примерно всё делают через интерфейсы и не всегда интерфейс можно заменить на абстрактный класс.
Такой вот костыль приделали, чтобы работало и плевать, что это идеологически неправильно и портит идею интерфейсов.

Doc>А пользователю библиотеки уже выбирать наследоваться от интерфейса или такого класса.


Весь прикол в том, что я даю API в виде условного интерфейса IPlugin, через который подтягиваю в приложение сторонние dll.
Если разработчики будут выбирать что реализуют, то мне у себя писать отдельные обработчики для интерфейсов и отдельные для классов?
А дальше я обновляю интерфейс для плагинов и у пользователей лотерея, в которой половина старых плагинов работает, т.к. наследовались от класса, а вторая половина на интерфейсе сидела и поломались?
Re[10]: Breaking change
От: Doc Россия http://andrey.moveax.ru
Дата: 13.12.22 10:26
Оценка: +1 -1
Здравствуйте, karbofos42, Вы писали:

Doc>>- интерфейс более не абстракция.

Doc>>- интерфейс знает о реализациях, иначе откуда такая уверенность что дефолтный G() подходит для всех реализаций интерфейса.
Doc>>- если по какой-то причине G() гарантированно подходит для любой реализации, то он может вполне себе быть extension методом.
Doc>>- программист реализации может просто не заметить добавления G(), который будет не корректный для его реализации. Но в проекте IA.G() рано или поздно кто-то вызовет.
K>Все эти проблемы присущи и абстрактному классу, на который ниже предлагается заменить такие интерфейсы

Абстрактный класс не интерфейс. Он поддерживает какой-то уровень абстракции, но при этом обладает реализацией и состоянием. Поэтому пункты выше в большей части к нему не применимы.

K>В C# нет множественного наследования, поэтому примерно всё делают через интерфейсы и не всегда интерфейс можно заменить на абстрактный класс.

K>Такой вот костыль приделали, чтобы работало и плевать, что это идеологически неправильно и портит идею интерфейсов.

— Можно было бы реализовать не трогая интерфейсы через абстрактные классы.
— У фичи достаточно узкая область применения, чтобы говорить что это замена множественного наследования.
— Но раз вы сами говорите что обсуждаемая фича — костыль, то какой смысл дальше обсуждать. Хороший код/фичу костылем не назовут
Re[11]: Breaking change
От: karbofos42 Россия  
Дата: 13.12.22 13:39
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>Абстрактный класс не интерфейс. Он поддерживает какой-то уровень абстракции, но при этом обладает реализацией и состоянием. Поэтому пункты выше в большей части к нему не применимы.


Применимы. Уровень абстракции достаточно условный и абстрактный класс в общем случае не обязан чем-то отличаться от интерфейсов.
Есть Stream и унаследованные от него MemoryStream, FileStream и какой-нибудь NetworkStream.
Много вот Stream знает про реализацию всего этого добра?
Метод расширения не является аналогом фичи по той причине, что он для всех реализаций интерфейса/наследников класса будет одинаковый,
а человекам нужно поведение по умолчанию с возможность перегрузки для конкретных реализаций.
Если в абстрактном классе добавить виртуальный метод с реализацией, то его добавление так же никто не заметит и не узнает, что можно теперь что-то перегрузить.

Doc>- Можно было бы реализовать не трогая интерфейсы через абстрактные классы.

Doc>- У фичи достаточно узкая область применения, чтобы говорить что это замена множественного наследования.

Было бы множественное наследование — думаю, что и фичу бы не добавляли, т.к. было бы доступно это всё через классы сделать.
По сути эта фича приближает интерфейсы к абстрактным классам и есть смысл это использовать там, где не получается взять классы.

Doc>- Но раз вы сами говорите что обсуждаемая фича — костыль, то какой смысл дальше обсуждать. Хороший код/фичу костылем не назовут


Ну, я просто не согласен, что у фичи есть полная альтернатива в языке.
Какой-нибудь "override new" для меня тоже костыль и я бы в язык это не добавлял, как и реализацию методов в интерфейсах.
Только разработчики языка почему-то со мной не советуются
Re[12]: Breaking change
От: Doc Россия http://andrey.moveax.ru
Дата: 13.12.22 14:38
Оценка: -1
Здравствуйте, karbofos42, Вы писали:

K>Применимы. Уровень абстракции достаточно условный и абстрактный класс в общем случае не обязан чем-то отличаться от интерфейсов.


Тот факт что у абстрактного класса может быть состояние уже меняет все. Как раз свести абстрактный класс к интерфейсу это не общий а частный случай.

K>Есть Stream и унаследованные от него MemoryStream, FileStream и какой-нибудь NetworkStream.

K>Много вот Stream знает про реализацию всего этого добра?

Не должен знать.

K>Метод расширения не является аналогом фичи по той причине, что он для всех реализаций интерфейса/наследников класса будет одинаковый,

K>а человекам нужно поведение по умолчанию с возможность перегрузки для конкретных реализаций.

Это от дизайна зависит можно использовать расширение или нет.

K>Было бы множественное наследование — думаю, что и фичу бы не добавляли, т.к. было бы доступно это всё через классы сделать.


Да не про множественное наследование эта фича.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#motivation
Это про добавление методов без ломки совместимости.
Re[13]: Breaking change
От: karbofos42 Россия  
Дата: 14.12.22 05:15
Оценка: +1
Здравствуйте, Doc, Вы писали:

Doc>Тот факт что у абстрактного класса может быть состояние уже меняет все. Как раз свести абстрактный класс к интерфейсу это не общий а частный случай.


А такой интерфейс имеет состояние или нет?
interface IA
{
  int Value {get;set;}
}


Doc>Это от дизайна зависит можно использовать расширение или нет.


Что от дизайна зависит? Возможность перегрузки метода расширения для разных типов, подобно виртуальным методам?

Doc>Да не про множественное наследование эта фича.


Да ладно?

Doc>Это про добавление методов без ломки совместимости.


И зачем же тогда эту фичу добавили в интерфейсы, если можно было спокойно вместо интерфейса брать класс и там это всё работало бы без изменений языка?
Re[14]: Breaking change
От: _NN_ www.nemerleweb.com
Дата: 14.12.22 05:19
Оценка: +2
Здравствуйте, karbofos42, Вы писали:

Doc>>Это про добавление методов без ломки совместимости.


K>И зачем же тогда эту фичу добавили в интерфейсы, если можно было спокойно вместо интерфейса брать класс и там это всё работало бы без изменений языка?


Тут уже был разбор как сделать множественное наследование чтобы не было проблем как с виртуальным наследованием в плюсах.
Можете поискать в раздели Философии.
Попробую найти.

Конкретно здесь .NET не умеет множественное наследование классов.
А множественное наследование интерфейсов умеет.
Почему единственным вариантом добавлять новую функциональность не ломая миллионы строк кода это методы по умолчанию в интерфейсе.
Как уже указали в Java аналогичная проблема и такое же решение.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[15]: Breaking change
От: karbofos42 Россия  
Дата: 14.12.22 08:48
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Почему единственным вариантом добавлять новую функциональность не ломая миллионы строк кода это методы по умолчанию в интерфейсе.

_NN>Как уже указали в Java аналогичная проблема и такое же решение.

Ну, вот в реальной жизни это действительно помогает?
Или спустя некоторое время вылезают неоднозначности и в итоге люди что-то городят своё?
Не лучше ли было не язык коверкать, а написать какой-нибудь фреймворк для плагинов, который бы генерировал нужные прокси и вызывал все эти дефолтные методы?
Что вот делать банально с переименованием метода?
Держать в итоге в интерфейсе и старое имя и новое? А если я просто в enum добавлю пару значений, то как быть? А если не добавлю, а изменю старые, т.к. решил теперь поддерживать Flags?
Эта фича же достаточно узкой выглядит и, на мой взгляд, через неё удобно быстро выкатить новые фишки в продакшон, а вот как это потом поддерживать и дальше расширять?
У меня просто не было задач, где это было бы нужно, потому на практике не использовал и тут чисто теоретический взгляд.
Re[16]: Breaking change
От: xpalex  
Дата: 14.12.22 10:37
Оценка: 41 (1) +1
Здравствуйте, karbofos42, Вы писали:

K>Здравствуйте, _NN_, Вы писали:


K>Эта фича же достаточно узкой выглядит и, на мой взгляд, через неё удобно быстро выкатить новые фишки в продакшон, а вот как это потом поддерживать и дальше расширять?

K>У меня просто не было задач, где это было бы нужно, потому на практике не использовал и тут чисто теоретический взгляд.

Эта фича, особенно в jave, гибрид сишарповых extension methods и с++ специализации.

Т.к. состояние класса в интерфейсе недоступно, реализация дефолтового метода может опираться только на существующий интерфес, что делает ее по возможностям полным аналогом extension method.
Но, конкретные реализации интерфейса, могут уже использовть внутренний стейт и переопределять дефолтовую реализацию более оптимальным образом.

Для c# выглядит оверкиллом. Хотя второй вариант может быть полезен.

interface ICountableEnumerable {
  bool next();

  int aCount() {
    int times = 0;
    while(next()) {
       times++;
    }
    return times;
  }
}

class List: ICountableEnumerable {
  int aCount() { return size; } // более оптимальная реализация
}


interface ICollectionWithFeatures {
  IReadonlyCollection asReadonly() {
    var copy = ...;// копируем исходный набор данных, что бы call-site не "сломался"
    return copy;
  }
}

class ReadonlyList: ICollectionWithFeatures, IReadonlyCollection {
  IReadonlyCollection asReadonly() {
    return this; // можно не копировать, т.к. мы не даем методов модификации текущей коллекции
  }
}
Re[3]: Diamond inheritance
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.12.22 22:02
Оценка: -1
Здравствуйте, Codealot, Вы писали:

C>Если у тебя такое произойдет, к какому интерфейсу приведешь — такой и должен быть вызван.


Публично то при таком раскладе чего реализовывать? Тут неоднозначность получается.

Вот они и сделали реализацию явной, а значит не видимую в публичном интерфейсе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Diamond inheritance
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.12.22 22:03
Оценка: +1
Здравствуйте, vsb, Вы писали:

vsb>java: types test.Test.I1 and test.Test.I2 are incompatible;

vsb> class test.Test.TestClass inherits unrelated defaults for method() from types test.Test.I1 and test.Test.I2

Это как раз не работает.

vsb>
vsb>  static class TestClass implements I1, I2 {
vsb>    @Override
vsb>    public void method() {
vsb>      I1.super.method();
vsb>    }
vsb>  }
vsb>


vsb>работает


А так и в Шарпе работает. Ты тупо объявил публичную функцию, которая переопределила дефолтную реализацию для обоих классов.
using System;

public class HelloWorld
{
    static void Main(string[] args)
    {
        var obj = new TestClass();
        obj.Method();
        I1 i1 = obj;
        i1.Method();
        I2 i2 = obj;
        i2.Method();
    }
}

interface I1
{
    void Method()
    {
        Console.WriteLine("I1");
    }
}

interface I2
{
    void Method()
    {
        Console.WriteLine("I2");
    }
}

class TestClass : I1, I2
{
    public void Method()
    {
        Console.WriteLine("TestClass");
    }
}


Ожидаемо выведет:
TestClass
TestClass
TestClass


Если в коде выше убрать публичный метод, то вызвать obj.Method(), а с кастом к интерфейсу прокатит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Breaking change
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.12.22 22:45
Оценка: +1 -1
Здравствуйте, Codealot, Вы писали:

C>Была, есть и будет есть. Не будет ее только в одном подклассе случаев — когда ты добавляешь метод, для которого можно написать дефолтную реализацию, которая имеет смысл по условиям задачи.


Я правильно понимаю, что это реинкарнация (второй аккаунт) сами знаете кого?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Breaking change
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.12.22 22:46
Оценка: +1 -1
Здравствуйте, Baiker, Вы писали:

B>Это в джамшутской терминологии "ломались". В нормальной: "все наследники получали корректирующую ошибку о недореализованном методе".


Увижу еще раз такой стиль общения, уйдешь в баню на долго. Пока не денёк.

Что касается обсуждаемого вопроса, в МС всё сделали правильно. Основная проблема в разработке сложного ПО — объем кода и сложность его поддержки, развития. Такое решение не создаёт лишние сложности, а значит упрощает жизнь. Каждый интерфейс может получить нужную ему дефолтную реализацию без лишних телодвижений со стороны программиста. Нам не придется бегать по классам и добавлять реализации вручную.

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

B>Спасибо, б%%%! Мало нам таймбомб — давайте теперь ещё и эти.


Несёшь форменный бред.

B>Не надо про УСЛОВНЫЕ СЛУЧАИ. Есть процесс разработки. Если у тебя есть библиотека и она обновилась, там всегда есть breaking changes. Хочешь — не обновляйся и ничего дореализовывать не надо. Хочешь свежачок — компильни, проверь ошибки, дореализуй контракт. Всё. Просто как день. Здесь не идёт вопрос об обратной совместимости — это эволюция продукта, где допустимо улучшение, требующее правки чужих исходников.


Случай не условный, а самый что не наесть конкретный. Сам недавно пользовался этой фичей — очень удобно. Просто не стоит путать публичный интерфейс класса и интерфейсы им реализуемые. Это могут быть разные реализации. Ты и в ручную можешь сделать несколько явных реализаций и публичный метод с тем же именем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Breaking change
От: Codealot Земля  
Дата: 14.12.22 23:01
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я правильно понимаю, что это реинкарнация (второй аккаунт) сами знаете кого?


Это такой хитрый наезд, что ли?
Ад пуст, все бесы здесь.
Re[4]: Diamond inheritance
От: Codealot Земля  
Дата: 14.12.22 23:01
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Публично то при таком раскладе чего реализовывать? Тут неоднозначность получается.


Ты не в курсе, как делается explicit implementation при конфликтах?
Ад пуст, все бесы здесь.
Re[2]: default interface methods. Какой все же бред.
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.12.22 23:03
Оценка: +1 -1
Здравствуйте, Baiker, Вы писали:

B>Я с большим подозрением стал относиться к "фичам" C# после версии 8.0; Такое ощущение, что все адекваты махнули рукой и сказали "А, лепите что хотите, я устал спорить!".


Создавай отдельные темы по отдельным фичам (как эта) — обсудим.

Лично мне не нравятся не фичи, а непоследовательность их появления и эволюционист. Авторы языка явно добавляли фичи по мере собственного созревания.

Судя по твоей критике ты пока что до этих фич не дорос.

B>Только так можно объяснить поток ОЧЕВИДНО СПОРНЫХ фич, которые обсуждаются хрен знает кем, одабриваются ещё более странными персонами и выкатываются в релиз без широкого обсуждения на общедоступных сайтах. (почему не LJ? Facebook? StackOverflow? Да потому что ТАМ НЕЛЬЗЯ ЗАТКНУТЬ РОТ ОППОНЕНТАМ! )


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

B>Унылые, обидчивые посредственности


Боюсь они даже о твоем существовании не подозревают.

B>выкатывают очередной высер их банального мозга


Истерика какая то, а толку — 0.

B>(или того хуже — плохо понятые фичи других языков) и начинается шапкозакидательство тех, кто смеет этих посредственностей критиковать. Более того — количество критики вообще никак не влияет на последущее решение — фича просто делается по задумке тупого индуса-придумщика и далее преподносится как очередной "прорыв". Я видел кучи обсуждений на мелкомягком междусобойчике в github и ты никогда не доведёшь свою мысль до их замкнутого разума.


У меня лично много претензий к C#. Но направление развития языка правильное. Все добавленные фичи — полезны. Моя главная претензия в том, что они добавлены эволюционным путём. Люди не проектировали язык как единое целое. По сему иногда встречаются недоработки. Но это явно не тот случай. Дефолтные реализации для интерфейсов сделаны не плохою.

B>Вот почему Nemerle — наше всё. Всегда можно общедоступно обсудить спорные моменты и более того — даже самому реализовать так, как ты считаешь нужным! Да, бывают в жизни и "две правды" сразу, но никто не имеет права принуждать тебя использовать "чужую" правду. У кого какие задачи — тот пусть себе и пилит "наименее спорный вариант" фичи.


В Немерле, к сожалению, такой фичи нет. Добавил бы, а не уставил здесь истерику. Тогда по праву мог бы говорить, что вот правильная реализации.

B>Вот дефолтовые методы в интерфейсах — я думал, это что-то полезное! Оказалось, высер.


Очень даже удобно. Недавно применил в реальном боевом проекте чтобы не писать кучу кода. В интерфейсе (который уже был) свойство выставил в одно значение, а в нужных классах реализации переопределил на обратное. Сэкономил море времени.

В том что эта фича не добавляет публичного метода, а создает явные реализации проблемы не вижу. Работа с членами интерфейса должна вестись через интерфейс. Иначе не нужен интерфейс, а нужно пользоваться наследованием реализаций и виртуальными методами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Breaking change
От: mogadanez Чехия  
Дата: 15.12.22 12:32
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Какую проблему вы здесь видите ?


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

не практике будет так:
* обновили библиотеку, ничего не упало, все работает
* спустя время кто-то из команды в интелисенсе найдет этот новый метод, заиспользует,
* если метод имеет какую то дефолтную реализацию — может даже покажется в начале что отлично работает
* спустя еще время потратят хренову тучу времени чтобы понять что мы вообще этот метод не реализовали, и отрабатывает какая то дефолтная заглушка


если уж очень хочется, как альтернатива, могли позволить указывать дефолтные методы, компиляция бы не падала, но всегда кидало бы NotImplemented exception
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.