Re[8]: Зависимости между классами и интерфейсами
От: AlexRK  
Дата: 16.09.20 18:35
Оценка:
Здравствуйте, ·, Вы писали:

ARK>>А нельзя так?

ARK>> List<Node> children;
·>Во-первых, шаблон List<Node> это таки отдельный тип, аналогичный NodeList с т.з. сабжа.

Не, это подпадает под одно из моих исключений, а именно: "Запрет на циклы — только на уровне объявлений".
То есть разница между NodeList и List<Node> в том, что объявление NodeList имеет зависимость от Node, а объявление List — нет.

·>Во-вторых, впрочем иногда таки нельзя, если понадобится расширить List специфичными для NodeList методами.


Вопрос в том, нужно ли NodeList знать про Node. Из приведенного примера это неочевидно.
Re: Зависимости между классами и интерфейсами
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.09.20 06:28
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Насколько плоха такая организация классов/интерфейсов в виде дерева, без циклов?

Как запишем
public class BinaryExpression: Expression
{
  public Expression Left {get;}
  public Expression Right {get;}
  public ExpressionType Type {get;}
}

?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Зависимости между классами и интерфейсами
От: AlexRK  
Дата: 17.09.20 09:29
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

ARK>>Насколько плоха такая организация классов/интерфейсов в виде дерева, без циклов?

S>Как запишем
S>
S>public class BinaryExpression: Expression
S>{
S>  public Expression Left {get;}
S>  public Expression Right {get;}
S>  public ExpressionType Type {get;}
S>}
S>

S>?

Так и запишем. BinaryExpression знает про Expression, здесь нет цикла _на уровне деклараций_. Вот если при этом Expression будет ссылаться на BinaryExpression в своем описании (или телах методов) — то да, цикл будет. Я веду речь именно о циклах на уровне описаний.

Если каждая сущность (класс или интерфейс) лежит в отдельном файле, то нельзя делать циклы вида "скщность из файла А используется в файле Б, если в файле Б уже используется сущность из файла А".
Re[3]: Зависимости между классами и интерфейсами
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.09.20 13:23
Оценка:
Здравствуйте, AlexRK, Вы писали:
ARK>Так и запишем. BinaryExpression знает про Expression, здесь нет цикла _на уровне деклараций_. Вот если при этом Expression будет ссылаться на BinaryExpression в своем описании (или телах методов) — то да, цикл будет. Я веду речь именно о циклах на уровне описаний.
Да, это я что-то не выспался.
ARK>Если каждая сущность (класс или интерфейс) лежит в отдельном файле, то нельзя делать циклы вида "скщность из файла А используется в файле Б, если в файле Б уже используется сущность из файла А".
Ну, давайте другой пример:
public interface IQueryable
{
  public IQueryProvider Provider {get;}
}

public interface IQueryProvider
{
  public IQueryable CreateQuery(Expression expression);
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Зависимости между классами и интерфейсами
От: · Великобритания  
Дата: 17.09.20 14:22
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>>>А нельзя так?

ARK>>> List<Node> children;
ARK>·>Во-первых, шаблон List<Node> это таки отдельный тип, аналогичный NodeList с т.з. сабжа.
ARK>Не, это подпадает под одно из моих исключений, а именно: "Запрет на циклы — только на уровне объявлений".
ARK>То есть разница между NodeList и List<Node> в том, что объявление NodeList имеет зависимость от Node, а объявление List — нет.
Вот ещё не совсем политкорректный пример
class Human
{ 
 short age;
 Male father;
 Female mother;
}
class Male extends Human
{
 long length;
}
class Female extends Human
{
 int size;
}


ARK>·>Во-вторых, впрочем иногда таки нельзя, если понадобится расширить List специфичными для NodeList методами.

ARK>Вопрос в том, нужно ли NodeList знать про Node. Из приведенного примера это неочевидно.
Всегда можно отделить введением дополнительной абстракции, но непонятно накой это всегда требовать.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Зависимости между классами и интерфейсами
От: AlexRK  
Дата: 17.09.20 14:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Ну, давайте другой пример:

S>
S>public interface IQueryable
S>{
S>  public IQueryProvider Provider {get;}
S>}

S>public interface IQueryProvider
S>{
S>  public IQueryable CreateQuery(Expression expression);
S>}
S>


Похоже на классический случай "владелец-элементы". В Queryable Provider точно нужен?
Re[10]: Зависимости между классами и интерфейсами
От: AlexRK  
Дата: 17.09.20 15:02
Оценка:
Здравствуйте, ·, Вы писали:

·>Вот ещё не совсем политкорректный пример

·>
·>class Human
·>{ 
·> short age;
·> Male father;
·> Female mother;
·>}
·>class Male extends Human
·>{
·> long length;
·>}
·>class Female extends Human
·>{
·> int size;
·>}
·>


Ну, это уже криминал. За такой код скоро и в тюрягу загреметь можно будет.

Надо, щоп все было в духе современных тенденций:
class Human
{ 
 short age;
 int numOfDicks;
 long breastSize;
 Human[] ascendants;
 Human[] descendants;
}


·>Всегда можно отделить введением дополнительной абстракции, но непонятно накой это всегда требовать.


Согласен. Просто пытаюсь понять, насколько это серьезное ограничение.
Re[5]: Зависимости между классами и интерфейсами
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.09.20 02:22
Оценка: 2 (1)
Здравствуйте, AlexRK, Вы писали:

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


S>>Ну, давайте другой пример:

S>>
S>>public interface IQueryable
S>>{
S>>  public IQueryProvider Provider {get;}
S>>}

S>>public interface IQueryProvider
S>>{
S>>  public IQueryable CreateQuery(Expression expression);
S>>}
S>>


ARK>Похоже на классический случай "владелец-элементы". В Queryable Provider точно нужен?

В этом дизайне — да.
В ранних версиях linq вся логика была спрятана в самом IQueryable; но потом оказалось, что логика построения запросов и логика исполнения запросов хорошо разделяются.
Поэтому вместо того, чтобы запихивать в IQueryable все эти Where, OrderBy, SelectMany и прочие, их запихали в extension-class Queryable:
    public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate) {
            if (source == null)
                throw Error.ArgumentNull("source");
            if (predicate == null)
                throw Error.ArgumentNull("predicate");
            return source.Provider.CreateQuery<TSource>( 
                Expression.Call(
                    null,
                    GetMethodInfo(Queryable.Where, source, predicate),
                    new Expression[] { source.Expression, Expression.Quote(predicate) }
                    ));
        }

Вот тут хорошо видно, зачем в IQueryable нужен Provider.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.