default interface methods. Какой все же бред.
От: Codealot Земля  
Дата: 11.12.22 18:52
Оценка: +1

static void Main(string[] args)
{
var obj = new TestClass();
obj.Method(); // error
}

interface ITest
{
void Method()
{
}
}

class TestClass : ITest
{
}

Вот за каким хреном так сделали?
Ад пуст, все бесы здесь.
Re: Diamond inheritance
От: Qbit86 Кипр
Дата: 11.12.22 19:15
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Вот за каким хреном так сделали?


Представь, что у тебя твой TestClass реализует не только интерфейс ITest, но и ICompletelyDifferentInterface:
internal interface ICompletelyDifferentInterface
{
    void Method() => Console.WriteLine(nameof(ICompletelyDifferentInterface));
}


Метод Method() какого интерфейса по-твоему должен быть вызван в вызове `obj.Method()`?
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Diamond inheritance
От: Codealot Земля  
Дата: 11.12.22 19:34
Оценка: +2 -1
Здравствуйте, Qbit86, Вы писали:

Q>Метод Method() какого интерфейса по-твоему должен быть вызван в вызове `obj.Method()`?


Если у тебя такое произойдет, к какому интерфейсу приведешь — такой и должен быть вызван.
Ад пуст, все бесы здесь.
Re: default interface methods. Какой все же бред.
От: vsb Казахстан  
Дата: 11.12.22 19:46
Оценка:
В жаве работает. А почему в C# ошибка?
Re[2]: Diamond inheritance
От: vsb Казахстан  
Дата: 11.12.22 19:49
Оценка: +1 -1
Здравствуйте, Qbit86, Вы писали:

C>>Вот за каким хреном так сделали?


Q>Представь, что у тебя твой TestClass реализует не только интерфейс ITest, но и ICompletelyDifferentInterface:

Q>
Q>internal interface ICompletelyDifferentInterface
Q>{
Q>    void Method() => Console.WriteLine(nameof(ICompletelyDifferentInterface));
Q>}
Q>


Q>Метод Method() какого интерфейса по-твоему должен быть вызван в вызове `obj.Method()`?


  interface I1 {
    default void method() {
      System.out.println("I1");
    }
  }

  interface I2 {
    default void method() {
      System.out.println("I2");
    }
  }

  static class TestClass implements I1, I2 {
  }


java: types test.Test.I1 and test.Test.I2 are incompatible;
class test.Test.TestClass inherits unrelated defaults for method() from types test.Test.I1 and test.Test.I2

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


работает
Re[3]: Breaking change
От: Qbit86 Кипр
Дата: 11.12.22 20:04
Оценка: 18 (1) +7
Здравствуйте, Codealot, Вы писали:

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


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

Представь, что твой класс TestClass реализует интерфейс ITest с методом Method() и интерфейс ICompletelyDifferentInterface без метода Method().
И потом автор второго интерфейса добавляет туда свой независимый метод Method().

Если использовать текущий подход C#, то есть изначально требовать явное приведение к нужному типу, то никакой неоднозначности не возникнет, и компиляция клиента не сломается.
Если по умолчанию разрешать вызов без приведения, то добавление нового метода Method() сломает компиляцию, то есть defeats the whole idea.
Глаза у меня добрые, но рубашка — смирительная!
Re: default interface methods. Какой все же бред.
От: karbofos42 Россия  
Дата: 11.12.22 20:13
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Вот за каким хреном так сделали?


Так правильно всё. Костыль/фича для интерфейсов сидит в интерфейсах, а не кочует по классам
Re[4]: Breaking change
От: Codealot Земля  
Дата: 11.12.22 20:16
Оценка:
Здравствуйте, Qbit86, Вы писали:

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

Q>С добавлением default interface methods — нет, больше не ломаются, и явно реализовывать новый API им не требуется.

Только в некотором подклассе случаев.

Q>Если по умолчанию разрешать вызов без приведения, то добавление нового метода Method() сломает компиляцию, то есть defeats the whole idea.


С фига ли? В большинстве случаев, таких проблем не будет.
defeats the whole idea — это когда у тебя производный класс не умеет то, что умеет базовый.
Ад пуст, все бесы здесь.
Re[2]: default interface methods. Какой все же бред.
От: Codealot Земля  
Дата: 11.12.22 20:19
Оценка: +1 -1 :))
Здравствуйте, vsb, Вы писали:

vsb>В жаве работает. А почему в C# ошибка?


Видимо, потому что опять кто-то допустил детишек-переростков до работы взрослых.

does not contain a definition for 'Method' and no accessible extension method 'Method' accepting a first argument of type 'Program.TestClass' could be found

Ад пуст, все бесы здесь.
Re[3]: Diamond inheritance
От: Qbit86 Кипр
Дата: 11.12.22 20:28
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>работает


Я не очень понял, в пользу какого тезиса ты приводишь этот пример.
(Джаву я не знаю, поверю написанному на слово.)
В твоём примере, чтобы был доступен метод method() в конкретном наследнике, пришлось его в этом наследнике реализовать, и вызвать там базовый метод, явно указав из какого предка его взять.
Такое и в C# будет работать, пример топик стартера был другой и не про это.
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: Работа взрослых
От: Qbit86 Кипр
Дата: 11.12.22 20:31
Оценка: +1
Здравствуйте, Codealot, Вы писали:

vsb>>В жаве работает. А почему в C# ошибка?


C>Видимо, потому что опять кто-то допустил детишек-переростков до работы взрослых.


Так ведь в приведённом примере на Джаве ещё хуже, там будет ошибка компиляции не на попытке вызова метода method(), а ещё на этапе попытки определить имплементора двух интерфейсов без явной реализации метода method():

java: types test.Test.I1 and test.Test.I2 are incompatible;
class test.Test.TestClass inherits unrelated defaults for method() from types test.Test.I1 and test.Test.I2

Глаза у меня добрые, но рубашка — смирительная!
Re[5]: Breaking change
От: Qbit86 Кипр
Дата: 11.12.22 20:35
Оценка: +4
Здравствуйте, Codealot, Вы писали:

C>С фига ли? В большинстве случаев, таких проблем не будет.


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

C>defeats the whole idea — это когда у тебя производный класс не умеет то, что умеет базовый.


Так он умеет — если работаешь через абстракцию.
Глаза у меня добрые, но рубашка — смирительная!
Re[6]: Breaking change
От: Codealot Земля  
Дата: 11.12.22 20:43
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Проблема будет в каждом таком случае, если в интерфейс добавляется метод, который уже есть в других реализуемых интерфейсах.


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

Q>Так он умеет — если работаешь через абстракцию.


Это ты о чем?
Ад пуст, все бесы здесь.
Re[4]: Работа взрослых
От: Codealot Земля  
Дата: 11.12.22 20:44
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Так ведь в приведённом примере на Джаве ещё хуже, там будет ошибка компиляции не на попытке вызова метода method(), а ещё на этапе попытки определить имплементора двух интерфейсов без явной реализации метода method():


А, так ты из любителей маскировать ошибки?
Ад пуст, все бесы здесь.
Re[5]: Работа взрослых
От: Qbit86 Кипр
Дата: 11.12.22 21:05
Оценка: +4 -2
Здравствуйте, Codealot, Вы писали:

Q>>Так ведь в приведённом примере на Джаве ещё хуже, там будет ошибка компиляции не на попытке вызова метода method(), а ещё на этапе попытки определить имплементора двух интерфейсов без явной реализации метода method():


C>А, так ты из любителей маскировать ошибки?


А у тебя и нет ошибки, если ты работаешь через абстракции — через ITest или через <TTest> where TTest : ITest. В C# ты это сделать можешь. В Джава (если верить написанному) — нет, потому что она даже не даст тебе определить имплементора.

C>А, так ты из любителей маскировать ошибки?


А, так ты из виртуалов Kolesiki, что ли? Я тогда не будут тратить на тебя время.
Глаза у меня добрые, но рубашка — смирительная!
Re[6]: Работа взрослых
От: Codealot Земля  
Дата: 11.12.22 21:24
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>В Джава (если верить написанному) — нет, потому что она даже не даст тебе определить имплементора.


Ты в этом так уверен?

Q>А, так ты из виртуалов Kolesiki, что ли?


Чувак, ты бредишь.
Ад пуст, все бесы здесь.
Re[4]: Diamond inheritance
От: vsb Казахстан  
Дата: 11.12.22 22:57
Оценка:
Здравствуйте, Qbit86, Вы писали:

vsb>>работает


Q>Я не очень понял, в пользу какого тезиса ты приводишь этот пример.


В пользу тезиса, что ромбовидное наследование является разрешимой проблемой.

Q>Такое и в C# будет работать, пример топик стартера был другой и не про это.


А как в C# это будет работать с интерфейсами?
Re[2]: Diamond inheritance
От: Baiker  
Дата: 12.12.22 10:47
Оценка: -2
Здравствуйте, Qbit86, Вы писали:

Q>Представь, что у тебя твой TestClass реализует не только интерфейс ITest, но и ICompletelyDifferentInterface:

Q>Метод Method() какого интерфейса по-твоему должен быть вызван в вызове `obj.Method()`?

Ты вот такую дурь пишешь, что не сразу поймёшь, что ты умный
Что значит "представь"?? Тебе УЖЕ ДАЛИ ЗАДАЧУ. Ясную как день. Что тебе ещё в ней непонятно? Есть класс, есть метод из интерфейса. И он ОБЯЗАН работать. По кр. мере по программерской логике. А теперь ты выдумываешь СВОЙ пример и что-то начинаешь доказывать. Зачем? Ответь на оригинальный вопрос!
Отредактировано 14.12.2022 13:36 VladD2 . Предыдущая версия .
Re[4]: Breaking change
От: Baiker  
Дата: 12.12.22 10:54
Оценка: +2
Здравствуйте, Qbit86, Вы писали:

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


Хм... а это что за идиотизм?? С чего бы это изменённый предок "не должен" ломать наследников? ЕЩЁ КАК ДОЛЖЕН!!
Если у тебя класс "ГеомФигура" и ты помимо "Площадь" добавил метод "Периметр", все наследники обязаны реализовать правильный метод "Периметр"!
Собственно, потому интерфейс и является КОНТРАКТОМ, что там нет "отлынивающих классов" — любой из наследников ОБЯЗАН корректно реализовать контракт.

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


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

Q>С добавлением default interface methods — нет, больше не ломаются, и явно реализовывать новый API им не требуется.


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

Q>Если по умолчанию разрешать вызов без приведения, то добавление нового метода Method() сломает компиляцию, то есть defeats the whole idea.


Не надо про УСЛОВНЫЕ СЛУЧАИ. Есть процесс разработки. Если у тебя есть библиотека и она обновилась, там всегда есть breaking changes. Хочешь — не обновляйся и ничего дореализовывать не надо. Хочешь свежачок — компильни, проверь ошибки, дореализуй контракт. Всё. Просто как день. Здесь не идёт вопрос об обратной совместимости — это эволюция продукта, где допустимо улучшение, требующее правки чужих исходников.
Re: default interface methods. Какой все же бред.
От: Baiker  
Дата: 12.12.22 11:08
Оценка:
Здравствуйте, Codealot, Вы писали:

C> obj.Method(); // error

C>Вот за каким хреном так сделали?

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

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

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