[Java vs. C#] Многократная реализация классом одного и того же интерфе
Почему жеПотому же, почему не реализован триллиард других более полезных фич.
Формулировка задачи --- Решение с необходиостью реализации одного и того же интерфейса.
Причем без всякого кода. Код отвлекает от поиска интуитивных программисту решений.
То, что ты написал на Java очень напоминает паттерн Factory только не для классов, а для интерфейсов.
Формулировка задачи --- Решение с необходиостью реализации одного и того же интерфейса.Я уже говорил про примеры в первом посте - сравнение даблов может быть реализовано по-разному в зависимости от конкретной ситуации.
А если заменить интерфейс на абстрактный класс, шарпу станет легче?
Я так понял, что нужен класс реализующий множество одинаковых интерфейсов, параметризованное чем-то (например для сравнения даблов параметр это точность). Почему нельзя добавить этот параметр в класс?
Он всячески используется в теле некоторой процедуры (только интерфейс но перед использованием необходимо выбрать его реализацию. Если бы для всех реализаций были бы имплементирующие классы, то просто фигарим обычную фабрику и выбираем. Но если необходимы некоторые реализации, которые нигде не имплементированы, или возвращать имплементирующие классы нельзя, потому что они жрут много памяти, то необходимо делать хрень, о которой написал пенартур. Получается что нужно делать двадцать имплементирующих классов и выбирать один из них, а в яве все ограничивается одним классом фабрики.
Почему нельзя добавить этот параметр в класс?В смысле?
Есть какая-то чужая либа, в которой есть какой-то метод, принимающий на вход объекты, реализующие интерфейс IEquatable. Иногда ты хочешь передавать туда даблы, сравнимые с какой-то точностью, а иногда - сравнимые идеально.
Есть какая-то чужая либа, в которой есть какой-то метод, принимающий на вход объекты, реализующие интерфейс IEquatable. Иногда ты хочешь передавать туда даблы, сравнимые с какой-то точностью, а иногда - сравнимые идеально.
public struct IndistinctDouble: IEquatable<IndistinctDouble>{
public double Value;
... //реализация обёртки с какой-то точностью
}
А вообще во всех уважающих себя либах должна быть перегрузка с IEqualityComparer<T>
Если подумать - интерфейс, в общем-то, ничем не отличается от функтора, просто в интерфейсе их несколько.приятно, что мои три дубля с разрывом в полтора года нашли отклик у читателей .
Почему же создатели языка не продумали создание объектов, реализующих заданный интерфейс, на лету? Почему не взяли это из джавы (где, насколько я понял, такая фича была с самого начала)?
Мое предположение, почему не реализовали в C#. Одна из распространенных задач, которую решают анонимные классы в Java — это написание обработчиков событий. В C# для этой задачи ввели специальный синтаксис делегатов и эвентов, который выигрывает у Java-анонимных классов, к тому же естественным образом поддерживает евенты в языках разметки ASP..NET и XAML. А про то, что анонимные классы могут быть полезны не только в эвентах, забыли или просто забили .
Можно надеяться, что в новых версиях C# этот промах заметят и введут синтаксис даже лучше, чем в Java — с выводом типов параметров, и с полным замыканием . Анонимные классы в Java не поддерживают полного замыкания, в отличие от лямбда выражений C#-а.
Для тех, кто программирует сегодня, рекомендую, не боятся вводить “лишний” интерфейс, там, где в Java напрашивались бы интерфейс + анонимные классы. Реализовывать этот интерфейс простыми вложенными приватными классами с передачей в конструкторе всего что нужно. Это несколько громоздко, но при работе в нормальной IDE это не сильно раздражает. Все известные мне варианты использовать в этих случаях делегаты выглядят жутко неестественно.
public struct IndistinctDouble: IEquatable<IndistinctDouble>{То есть, заводим обёртку на каждый случай жизни.
Это даже бОльшее говно, чем мой второй вариант (с лямбдами).
А вообще во всех уважающих себя либах должна быть перегрузка с IEqualityComparer<T>IEquatable было примером.
У тебя все функции, принимающие на вход экземпляр какого-то интерфейса, могут принимать на вход и какой-то совершенно другой объект+описание того, как с ним работать? Интерфейсы, вообще-то, для этого и придумывались.
Анонимные классы в Java не поддерживают полного замыкания, в отличие от лямбда выражений C#-а.А что в java не так?
А что в java не так?в анонимном классе нельзя обращаться к переменным метода, где объявлен анонимный класс, если переменная не помечена finaly, т.е. типа readonly переменная.
Я думаю, в Sun-е тоже сидят не дураки, обещают и сделают в Java и замыкания, и лямбды. И все будет ка-ра-шо.
в анонимном классе нельзя обращаться к переменным метода, где объявлен анонимный класс, если переменная не помечена finaly, т.е. типа readonly переменная.Как мне сейчас кажется, это не так уж и страшно.
К приватным полям объекта ведь можно обращаться?
Пусть сначала дженерики нормальные сделают.
Да уже есть Груви, в общем-то.
Есть какая-то чужая либа, в которой есть какой-то метод, принимающий на вход объекты, реализующие интерфейс IEquatable. Иногда ты хочешь передавать туда даблы, сравнимые с какой-то точностью, а иногда - сравнимые идеально.А чем плохо сделать обертку над дабл, содержащую значение дабл и точность сравнения. В либу передаем эту обертку, предварительно выставляя точность.
А чем плохо сделать обертку над дабл, содержащую значение дабл и точность сравнения. В либу передаем эту обертку, предварительно выставляя точностьТы ещё спроси, зачем нужны лямбды, если вместо них можно просто заводить специальные классы (на каждую лямбду по классу) и передавать туда нужные переменные по референсу.
Если нельзя анонимные - ну пусть будут с именами.
По сути ниже - то же самое, хотя отсутствие синтаксического сахара в виде анонимных классов заставляют явно указать
а) имена классов реализаций (что неплохо, ибо реализации чем-то отличаются и это отличие можно коротенько описать в имени)
б) объекты реализаций нуждаются в каких-то данных провайдера реализаций (code).
class A {
public string code = "undefined";
class Impl1_of_I: I
{
A factory;
public Impl1_of_I(A factory) { this.factory = factory; }
public void DoSomething {
Console.WriteLine("Object of A with code " + factory.code + " is provides object of I with first way");
}
};
public I AsI1 {
return new Impl1_of_I(this);
}
class Impl2_of_I: I {
A factory;
string parameter;
public Impl2_of_I(A factory, string parameter) { this.factory = factory; this.parameter = parameter; }
public void DoSomething {
Console.WriteLine("Object of A with code " + factory.code + " provides object of I with second way and parameter " + parameter);
}
};
public I AsI2(string parameter) {
return new Impl2_of_I(this, parameter) ;
}
}
Если же мы хотим, чтобы объект класса A реализовывал интерфейс I, нам надо от него занаследоваться, ну а реализации методов могут зависеть от параметров переданных в конструктор. В этом случае класс A может поддерживать несколько реализаций интерфейса, но объект класса A - только один, в зависимости от его параметров.
IEquatable было примером.У тебя все функции, принимающие на вход экземпляр какого-то интерфейса, могут принимать на вход и какой-то совершенно другой объект+описание того, как с ним работать? Интерфейсы, вообще-то, для этого и придумывались.В BCL так и сделано. Не понимаю, чем тебя не устраивает.
Что-то я не пойму, а где в твоём примере реализация интерфейса может работать с private членами класса? Или со вложенными классами такое будет работать? (лень проверять)
Или со вложенными классами такое будет работать? (лень проверять)по средством форума penartur осваивал тонкости языка C# . Да, такой доступ имеется, в этом то и фишка.
Как мне сейчас кажется, это не так уж и страшно.в реальности это создает проблемы, тут на форуме был тред с примером на эту тему
по средством форума penartur осваивал тонкости языка C#Тонкости я осваиваю посредством редактора и документации; просто ни разу не надо было из вложенных классов обращаться к внешним.
Я бы даже сказал, что ты не должен этого хотеть (использовать в лямбде mutable локальную переменную).
Оставить комментарий
kruzer25
Классы могут реализовывать сразу несколько разных интерфейсов; конфликты имён разрешаются с помощью явного указания имени интерфейса перед именем метода.Если развить эту идею немного дальше - может оказаться, что класс должен реализовывать несколько одинаковых интерфейсов. Если развить ещё дальше - выйдет, что класс должен реализовывать бесконечное количество интерфейсов (например, Double может реализовывать IEquatable со строгой проверкой на равенство, и с параметром опустимого различия между числами, чтобы они ыли признаны равными). Конечно, хочется этого не просто так, а чтобы потом передать на вход куда-то, где ожидают экземпляр этого интерфейса; значит, приведение объекта к нужному типу будет осуществляться не стандартными средствами приведения типов, а, например, у объекта будут методы вроде AsI1, AsI2 etc.
В джаве, насколько я понимаю, всё это замечательно решается через анонимные классы:
(естественно, код нерабочий, потому что джаву я не знаю).
В C# для этого придётся городить два новых класса (хотя нет, только один новый класс явно реализующих I, принимающих на вход лямбду DoSomething получится очень запутано:
Если даже упростить задачу, и требовать реализации конечного заранее определённого количества интерфейсов - интуитивно работающий (и, имхо, самый простой из всех трёх примеров) говнокостыль оказывается нерабочим:
то есть, всё равно придётся городить огород с дополнительным классом, что в случае, когда в интерфейсе хотя бы десять методов с кучей параметров, становится уже совершенно ужасным.
Если подумать - интерфейс, в общем-то, ничем не отличается от функтора, просто в интерфейсе их несколько.
Почему же создатели языка не продумали создание объектов, реализующих заданный интерфейс, на лету? Почему не взяли это из джавы (где, насколько я понял, такая фича была с самого начала)?