Впервые подагра у меня возникала на фоне употребления в пищу говяжих почек. Конечно можно сказать что количество почек по сравнению с остальной едой смешное. Также симптомы начинали появлятся на фоне употребления острого перца — а ведь его количество смехотворно.
>> Для использовании наследования, Builder разделяется на две части (один с полями, другой — с методом создания) следующим образом:
Так делать не стоит, сейчас объясню почему
Это написано про минимальный билдер, который сооружается из double brace initialization, а он не является fluent-интерфейсом.
Mega Builder является fluent-интерфейсом, но он не может поддерживать такого сокращённого наследования с помощью пареадресации унаследованному билдеру, поскольку в унаследованном классе могут быть вообще совершенно другие валидные сочетания параметров, и поэтому их надо полностью описывать заново.
В статье есть все ссылки на описываемый код: github.com/speaking-fish/java-sf-builder-megagithub.com/speaking-fish/java-sf-builder-simple-example
Пример билдера который никак нельзя воткнуть ни в конструктор ни в основной билдер:
public class LocalBuilderExample {
protected final double base;
public LocalBuilderExample(double base) {
super();
this.base = base;
}
public class BaseBuilder extends NewBaseClass.BuilderImpl {
public NewBaseClass create() {
if(!Double.isNaN(base)) {
first = (int) Math.round(base) + first;
if(!Double.isNaN(base)) {
second = base + second;
} else {
second = base;
}
}
return new NewBaseClass(this);
};
}
}
Вы предлагаете в таком случае дублировать все описания параметров вместе со всеми дефолтными значениями.
Скажем, вот код, эквивалентный вашим NewBaseClass.java и NewChildClass.java (где-то в два раза короче):
В вашем коде не хватает констант для дефолтных значений — это соответственно увеличит код.
Добавим их и сравним построчно код игнорируя пустые строки (я убрал модификаторы доступа чтобы влезло):
C# Java
class BaseClass { = class BaseClass {
+ static class BuilderImpl {
+ int first = -1 ;
+ double second = Double.NaN;
+ String third = null ;
+ }
+5
+ static class Builder extends BuilderImpl {
+ BaseClass create() { return new BaseClass(this); }
+ }
+3
const int DEFAULT_First = -1 ; +
const double DEFAULT_Second = double.NaN; +
const string DEFAULT_Third = null ; +
+3
const int First { get; } = final int first ;
const double Second { get; } = final double second;
const string Third { get; } = final String third ;
+ int first () { return first ; }
+ double second() { return second; }
+ String third () { return third ; }
+3
BaseClass( = BaseClass(
int first = DEFAULT_First , = BuilderImpl builder
double second = DEFAULT_Second, +
string third = DEFAULT_Third , +
) { +2= ) {
First = first; = this.first = builder.first ;
Second = second; = this.second= builder.second;
Third = third; = this.third = builder.third ;
} = }
} = }
=12
+5 +11
+6
17 23
class ChildClass : BaseClass { = class ChildClass extends BaseClass {
+ static class BuilderImpl extends BaseClass.BuilderImpl {
+ Object fourth = null;
+3 }
+ static class Builder extends BuilderImpl {
+ ChildClass create() { return new ChildClass(this); }
+3 }
const object DEFAULT_Fourth = null; +
+1
const object Fourth { get; } = final Object fourth;
+ Object fourth() { return fourth; }
+1
ChildClass ( = ChildClass(
int first = DEFAULT_First , = BuilderImpl builder
double second = DEFAULT_Second, +
string third = DEFAULT_Third , +
object fourth = DEFAULT_Fourth +
) : base( +3= ) { super(
first , = builder
second, +
third +
) { +2= );
Fourth = fourth; = this.fourth = builder.fourth;
} = }
} = }
=10
+6 +7
+1
16 17
=22
+11 +18
+7
33 40
В сухом остатке:
Базовый класс в варианте с билдером примерно на четверть больше а не в два раза.
Наследник первого уровня примерно такой же.
Если брать два этих класса суммарно, то в Java будет примерно на четверть больше.
Понятно, что с добавлением уровней наследования вариант с именованными параметрами растёт, а вариант с билдером практически остается одинаковым.
Вывод: Если у вас один класс у которого нет наследников, то однозначно именованные параметры короче.
Если у класса есть наследники второго и более уровней, то однозначно билдер проще.
Ну конечно в варианте с большим количеством параметров гораздо легче ошибиться (несоответствие типа, несоответствие порядка)
В C# 7 планируется сделать что-то вроде этого
Генерация конструкторов? Но тогда проверки сделать не получится.
По своему опыту не рекомендавал бы «реминерализующие» добавки в том числе и SPLAT Биокальций людям склонным к подагре. При этом другими SPLAT пользуюсь нормально.
По поводу варианта А — в этом случае наверное не может быть final полей и не могут выполнятся проверки.
Вот вариант Б — да, именованные параметры со значениями по умолчанию сделали бы многие простые билдеры ненужными, однако…
Сейчас я добавил сокращённые версии классов с минимальным билдером. Там по новым ссылкам можно их увидеть github.com/speaking-fish/java-sf-builder-simple-example — классы New*
В них в конструктор класса передаются не все параметры, а только билдер. Т.е. теперь не надо перечислять все параметры в функциях.
Вы же согласны что лучше иметь сложные проверки отдельно от конструктора, в билдере.
Т.е. тогда в C# билдер останется, но не отдельным классом а отдельной функцией, так?
Тогда возникает вопрос, а как будет работать наследование?
Если у меня наследуется класс билдера — то он наследует все свои поля и их потом не надо опять все перечислять.
А что с параметрами функции? Их можно унаследовать или в унаследованных классах придётся как перечислять всё больше и больше параметров и делать какие-то проверки чтобы их случайно не упустить, и в каждом классе потом искать и исправлять дефолтные значения или определять еще для них константы и использовать константы?
Поясните этот момент.
Это вообще скорее не C# касается, а всех языков с возможностью использования именованных параметров функций.
Т.е. в результате, отдельный класс билдера будет проще использовать и в таких языках.
PS. А инициализация коллекций и словарей многоуровневая или только первый уровень поддерживается?
Книга двух английских авторов, ученого и журналиста, в увлекательной форме рассказывает о современном уровне и перспективах развития одной из самых молодых наук — искусственного интеллекта, о создании «умных» машин, которые все решительнее внедряются во все сферы человеческой деятельности: производство, науку, административно-управленческую деятельность, транспорт и даже искусство.
Адресована всем, кто интересуется достижениями современной науки и техники.
Содержание
Новые знания от ЭВМ
1. Слепой поиск и незнание
2. Машина становится экспертом
3. Машинные и человеческие возможности
4. Мысли о мышлении
5. Опыт и открытие
6. Созидание нового знания
7. Метафора наизнанку
8. На пути к модельным небесам
9. А была ли кошка?
10. Изобретения на благо человечества
В книге рассказывалось о различных аспектах ИИ — о восприятии и анализе информации, шахматах, экспертных системах, системах логического вывода и многом другом.
Даже в википедии есть ссылки на эту книгу: шахматы, Eurisko.
Да вы правы, такое не прокатит.
Но, в общем, все уже привыкли не только к особенностям анонимных классов, но и вовсю используют лямбды Java 8 и знают про final/effectively final.
Я например чаще использую for each, тогда в аналогичном коде для Java 8+ ничего не надо будет менять, только для Java < 8 надо будет добавить final:
for(final int i : new int[] {1,2,3}) {
new MyClass.Builder(){{ first = i; third = "3"; }}.create();
}
Идея обвязывать заодно первый уровень коллекций интересная.
По идее, если уж так делать, то можно было бы и следующие уровни обвязывать и не только коллекций но и просто вложенных классов.
Почему коллекции инициализируются только или элементами ли коллекциями? Что если я использую ленивые итераторы?
Непонятно в каком месте реализовывать валидацию.
Посмотрел сгенерированный код projectlombok.org/features/Singular-snippet.html
Метод public SingularExample build() как-то переусложнён — всё это можно было бы спокойно вынести в хелперы.
Почему списки билдера инициализируются ArrayList а не LinkedList?
Непонятно как организовать обязательные поля и как соорудить контекстно-зависимый билдер.
То есть если ветер такой слабый, то буря не смогла раскачать МВА, антенна не смогла сорваться и с Уотни ничего не случилось? О боже, как я теперь смогу спокойно посмотреть фильм?
Тоже копал в эту сторону. В результате пока сделал обмен через стандартные пайпы ввода-вывода на Java/C++/Pascal Linux/Windows intel/ARM. Но у меня пока синхронный rpc. Делал для простого разделения на процессы, миграции по частям, заворачивания ненадёжных dll в перезапускаемые процессы… Пока в планах стыки на javascript и python. Вообще, дальше в планах добавить к этому shared memory для текущего обрабатываемого пула данных на memory-mapped файлах, чтобы в части случаев не просто сократить передачу данных через пайпы но и вообще избежать её.
«А поскольку топлива будет потрачено мало, то больше энергии останется для обеспечения работы научных инструментов станции.»
Какая тут связь? Двигатели химические на метилгидразине а не ионники, энергоустановка — РИТЭГ а не топливные элементы.
Для целей считывания/записи одновременно двух секторов одного цилиндра — смысла нет. Но для разных цилиндров таки есть, поскольку экономится время позиционирования. Ну и скорость передачи данных будет больше в два раза, хоть и ценой двукратного увеличения стоимости, но зато в одном корпусе.
В момент выхода Windows 95, по сравнению с существующей OS/2 Warp была просто пустой оболочкой для вызова старых 16-битных программ оставшихся от Win3.11. Должно было ещё пройти время чтобы софт начал появляться.
ps. А диалоги неизменяемого размера в винде до сих пор.
Это написано про минимальный билдер, который сооружается из double brace initialization, а он не является fluent-интерфейсом.
Mega Builder является fluent-интерфейсом, но он не может поддерживать такого сокращённого наследования с помощью пареадресации унаследованному билдеру, поскольку в унаследованном классе могут быть вообще совершенно другие валидные сочетания параметров, и поэтому их надо полностью описывать заново.
В статье есть все ссылки на описываемый код: github.com/speaking-fish/java-sf-builder-mega github.com/speaking-fish/java-sf-builder-simple-example
Вы предлагаете в таком случае дублировать все описания параметров вместе со всеми дефолтными значениями.
В вашем коде не хватает констант для дефолтных значений — это соответственно увеличит код.
Добавим их и сравним построчно код игнорируя пустые строки (я убрал модификаторы доступа чтобы влезло):
В сухом остатке:
Базовый класс в варианте с билдером примерно на четверть больше а не в два раза.
Наследник первого уровня примерно такой же.
Если брать два этих класса суммарно, то в Java будет примерно на четверть больше.
Понятно, что с добавлением уровней наследования вариант с именованными параметрами растёт, а вариант с билдером практически остается одинаковым.
Вывод: Если у вас один класс у которого нет наследников, то однозначно именованные параметры короче.
Если у класса есть наследники второго и более уровней, то однозначно билдер проще.
Ну конечно в варианте с большим количеством параметров гораздо легче ошибиться (несоответствие типа, несоответствие порядка)
Генерация конструкторов? Но тогда проверки сделать не получится.
Можно пример?
Вот вариант Б — да, именованные параметры со значениями по умолчанию сделали бы многие простые билдеры ненужными, однако…
Сейчас я добавил сокращённые версии классов с минимальным билдером. Там по новым ссылкам можно их увидеть github.com/speaking-fish/java-sf-builder-simple-example — классы New*
В них в конструктор класса передаются не все параметры, а только билдер. Т.е. теперь не надо перечислять все параметры в функциях.
Вы же согласны что лучше иметь сложные проверки отдельно от конструктора, в билдере.
Т.е. тогда в C# билдер останется, но не отдельным классом а отдельной функцией, так?
Тогда возникает вопрос, а как будет работать наследование?
Если у меня наследуется класс билдера — то он наследует все свои поля и их потом не надо опять все перечислять.
А что с параметрами функции? Их можно унаследовать или в унаследованных классах придётся как перечислять всё больше и больше параметров и делать какие-то проверки чтобы их случайно не упустить, и в каждом классе потом искать и исправлять дефолтные значения или определять еще для них константы и использовать константы?
Поясните этот момент.
Это вообще скорее не C# касается, а всех языков с возможностью использования именованных параметров функций.
Т.е. в результате, отдельный класс билдера будет проще использовать и в таких языках.
PS. А инициализация коллекций и словарей многоуровневая или только первый уровень поддерживается?
www.ozon.ru/context/detail/id/28159440/?utm_source=livelibru&utm_medium=partner
www.libex.ru/detail/book58203.html
В книге рассказывалось о различных аспектах ИИ — о восприятии и анализе информации, шахматах, экспертных системах, системах логического вывода и многом другом.
Даже в википедии есть ссылки на эту книгу: шахматы, Eurisko.
habrahabr.ru/post/233797
---Add elements ( 6kk )
LinkedList: 2264 ms
ArrayList: 493 ms
ArrayList is faster
Но, в общем, все уже привыкли не только к особенностям анонимных классов, но и вовсю используют лямбды Java 8 и знают про final/effectively final.
Я например чаще использую for each, тогда в аналогичном коде для Java 8+ ничего не надо будет менять, только для Java < 8 надо будет добавить final:
По идее, если уж так делать, то можно было бы и следующие уровни обвязывать и не только коллекций но и просто вложенных классов.
Почему коллекции инициализируются только или элементами ли коллекциями? Что если я использую ленивые итераторы?
Непонятно в каком месте реализовывать валидацию.
Посмотрел сгенерированный код projectlombok.org/features/Singular-snippet.html
Метод public SingularExample build() как-то переусложнён — всё это можно было бы спокойно вынести в хелперы.
Почему списки билдера инициализируются ArrayList а не LinkedList?
Непонятно как организовать обязательные поля и как соорудить контекстно-зависимый билдер.
Какая тут связь? Двигатели химические на метилгидразине а не ионники, энергоустановка — РИТЭГ а не топливные элементы.
ps. А диалоги неизменяемого размера в винде до сих пор.