Будет ли синтаксис для composition полезным дополнением к Java?[закрыто]

StackOverflow https://stackoverflow.com/questions/254276

Вопрос

Во-первых, я почти ничего не знаю о теории языков, и я едва знаю какие-либо другие языки, кроме Java, но у меня была идея, которая, я думаю, была бы классной, но мне нужно, чтобы вы, ребята, рассказали мне:
a:почему это отстой
b:как у language x было это в течение многих лет
c:как засасывает мой разум
d:все вышеперечисленное

Идея придала бы композиции такую же простоту повторного использования кода, что extends делает.

Итак, если бы у вас был такой класс, как этот:

public interface A {  
    public void methodInA();  
}

А потом у вас был такой урок, как этот:

public class B {  
    private composed A;
    public B() {
        // construct A within constructor
    }
}

Тогда вы смогли бы сделать это:

B myB = new B();
myB.methodInA();

Без необходимости добавлять делегирование в классе B.Но вы также могли бы сделать то же самое, что и с наследованием, т. е.:

@Overrides
public void methodInA(){
    // B's own delegation method
}

К недостаткам относятся:

  • методы скрыты в исходном коде, что делает менее очевидным, откуда исходит вызов, но это также относится к extends
  • если составные поля используют одну и ту же сигнатуру метода, необходимо разрешить конфликт (как это решают конфликтующие интерфейсы?).
  • если бы вы хотели иметь несколько составных полей одного и того же типа, возник бы очевидный конфликт в отношении того, какое поле делегировать
  • вероятно, еще 100 вещей, о которых я не подумал

Как я уже сказал, я, очевидно, не специалист по теории языка, и я не тратил целую вечность на размышления об этом, эта идея просто пришла мне в голову, и я хотел знать, насколько я ошибаюсь.Я просто думаю, что это было бы в некотором роде круто.

Это было полезно?

Решение

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

Лично я ненавижу наследование конкретных классов.Я большой сторонник пункта 14 от Блоха Эффективная Java, Предпочтение композиции перед наследованием.Я думаю, что что-то подобное немного упростило бы реализацию идиомы, которую он рекомендует в этом пункте.

Честно говоря, если бы вы действительно знали, что делаете, я готов поспорить, что вы могли бы написать аннотацию компилятора, которая справилась бы с этим.Итак, предполагая, что у вас есть класс Bar, который реализовал интерфейс IBar, ваш класс будет выглядеть следующим образом:

public class Foo {

  @Delegate(IBar.class)
  private Bar bar;

  // initialize bar via constructor or setter
}

Затем во время компиляции Foo можно было бы заставить реализовать IBar, и любой из методов в этом интерфейсе, которые еще не были реализованы Foo, в конечном итоге был бы сгенерирован, чтобы выглядеть следующим образом:

public Baz method1(Qux val) {
  return bar.method1(val);
}

Как упоминалось выше, вы хотели бы установить ограничение, чтобы только одно поле для каждого класса могло использовать эту аннотацию.Если бы эта аннотация содержалась в нескольких полях, вы, вероятно, захотели бы выдать ошибку компиляции.В качестве альтернативы вы могли бы придумать способ закодировать какую-то модель приоритета в передаваемые ей параметры.

Теперь, когда я это написал, это кажется довольно крутым.Может быть, я поиграю с этим на следующей неделе.Я обновлю это, если мне удастся что-нибудь выяснить.

Другие советы

Это звучит круто, но я думаю, что это приводит к некоторым ужасным языковым конструкциям.Очевидно, что возникает проблема, если вы объявляете более одной "композиции" одного и того же класса, но даже если вы запрещаете это, как насчет случая, когда вызов соответствует методу в более чем одном из (разных) составленных классов?Вам пришлось бы указать, какой из них был вызван в основном классе, и для этого вам понадобился бы дополнительный синтаксис.Ситуация становится еще хуже, если в классах есть публичные участники.

Композиция используется для предотвращения проблем с множественным наследованием.Разрешение подобной композиции фактически разрешает множественное наследование, по крайней мере, с точки зрения разрешения того, какой метод вызывать.Поскольку ключевым дизайнерским решением в Java было запретить множественное наследование (по уважительным причинам) Я думаю, маловероятно, что это когда-либо будет введено в Java.

Однако я не уверен, что вижу в этом явное преимущество.Я понимаю, к чему вы клоните.На данный момент, чтобы вызвать метод на A, вам нужно myB.getAInstance().methodInA() , но вы хотите сделать это myB.methodInA().

Но что произойдет, если у вас есть несколько экземпляров A?Как был бы разрешен вызов метода?Часто композиция подразумевает ассоциацию "один ко многим", поэтому B имеет много экземпляров A.Что происходит тогда?

Я согласен с перечисленными вами недостатками.Это может просто вызвать слишком большую путаницу, чем того стоит.

Ознакомьтесь с тем, что называется "Mixins" на некоторых языках и "Roles" в OO-системе Perl 5 Moose.

Существует также разница между состав и агрегация чтобы обдумать.Как компилятор узнает, имеете ли вы в виду отношения 'is-a' или 'has-a'?

  • Становится ли весь объектный граф пригодным для сборки мусора или только его верхняя часть?

Пара инструментов отображения ORM и фреймворков поверх / вокруг них обеспечивают belongsTo или has-many связи между постоянными объектами и некоторыми другими также предусматривают каскадное удаление (для композиции).Я не знаю ни одного готового решения, которое предоставляло бы простой синтаксический сахар, который вы ищете.

На самом деле, если подумать, метакласс Groovy и идиома (ы) метапрограммирования могут предоставить нечто очень похожее с делегированием "автоматической магии".

Множественное наследование разрешено в C ++, я знаю, что это другое, но это тот же мыслительный процесс.Java была разработана таким образом, чтобы не допускать множественного наследования, чтобы было меньше путаницы, следовательно, ошибок и эксплойтов.

То, что вы предложили, находится в прямом противоречии с принципами java.

Сказав это, это было бы круто (не обязательно полезно).Я программист на Java, который перешел с C ++.Мне нравится иметь возможность совершать свои собственные ошибки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top