Типизация одного уровня дерева
От: Аноним  
Дата: 13.07.09 09:26
Оценка:
Есть некий обобщенный интерфейс для всех элементов дерева. Например

public interface IElement
{
   public string Name{ get; }

   public List<IElement> Childs;
}


Но есть условие, что элементы одного уровня должны иметь один тип.

То есть следующее добавление не допустимо :

 IElement el = new OneElement();
 el.Childs.Add( SecondElement() );
 el.Childs.Add( ThirdElement() );


правильной является следующая конструкция

 IElement el = new OneElement();
 el.Childs.Add( SecondElement() );
 el.Childs.Add( SecondElement() );


То есть все дочерние элементы одного уровня должны быть строго одного типа, как вот описать подобную конструкцию ?


14.07.09 01:25: Перенесено модератором из 'Архитектура программного обеспечения' — Кодт
Re: Типизация одного уровня дерева
От: komaz Россия  
Дата: 13.07.09 11:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть некий обобщенный интерфейс для всех элементов дерева. Например


А>
А>public interface IElement
А>{
А>   public string Name{ get; }

А>   public List<IElement> Childs;
А>}
А>


А>Но есть условие, что элементы одного уровня должны иметь один тип.


А>То есть следующее добавление не допустимо :


А>
А> IElement el = new OneElement();
А> el.Childs.Add( SecondElement() );
А> el.Childs.Add( ThirdElement() );
А>


А>правильной является следующая конструкция


А>
А> IElement el = new OneElement();
А> el.Childs.Add( SecondElement() );
А> el.Childs.Add( SecondElement() );
А>


А>То есть все дочерние элементы одного уровня должны быть строго одного типа, как вот описать подобную конструкцию ?


Забыл шарпы, мож чего и можно с женериками намутить. А нельзя обойтись как-нибудь так?
public interface IElement {
    String getName();

    Class<?> getType();
    
    //вернет read-only list
    List<IElement> getChildren();

    //выполнит проверку типов
    add(IElement child);
}
Re: Типизация одного уровня дерева
От: kometa_triatlon  
Дата: 13.07.09 15:04
Оценка:
Ну если максимальная глубина дерева конечна и заранее известна, то можно попробовать что-то такое:

public interface IElement<T> {
        string Name { get; }

        List<T> Children { get;}
    }

    public interface IElement<T> {
        string Name { get; }

        List<T> Children { get;}
    }

    public abstract class BaseElement<T> : IElement<T> {
       
        public string Name {
            get { return "name"; }
        }

        private readonly List<T> children = new List<T>();
        public List<T> Children {
            get { return children; }
        }
    }

    public class FirstElement<T> : BaseElement<T> {        
    }

    public class SecondElement<T> : BaseElement<T> {
        
    }

    public class LastLevelElement {
    }


В данном случае Т — тип дочерних узлов.
Но в таком случае при создании узла нужно будет указывать типы допустимых детей аж до последнего уровня:

var el = new FirstElement<SecondElement<LastLevelElement>>();


Зато будет статическая типизация:

el.Children.Add(new SecondElement<LastLevelElement>());
el.Children[0].Children.Add(new LastLevelElement());


И да, последний уровень не должен наследоваться от дженерика, иначе получишь хардверный stack overflow

Ну а иначе — динамическая проверка при добавлении, если тип не подходит — исключение.
Re: Типизация одного уровня дерева
От: _FRED_ Черногория
Дата: 14.07.09 02:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть некий обобщенный интерфейс для всех элементов дерева. Например

А>   public List<IElement> Childs;


http://rsdn.ru/forum/dotnet/3306864.aspx
Автор: _FRED_
Дата: 27.02.09


А>Но есть условие, что элементы одного уровня должны иметь один тип.


Строго один? Или некий тип и, возможно, его наследников? То есть, "следующее добавление допустимо", если ThirdElement является наследником SecondElement или нет?

А> IElement el = new OneElement();
А> el.Childs.Add( SecondElement() );
А> el.Childs.Add( ThirdElement() );

?
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Типизация одного уровня дерева
От: HowardLovekraft  
Дата: 14.07.09 07:28
Оценка:
Здравствуйте, kometa_triatlon, Вы писали:

_>Но в таком случае при создании узла нужно будет указывать типы допустимых детей аж до последнего уровня:


Я бы сделал так:
    interface INode<T>
    {
        ICollection<T> Children { get; }
    }

    interface INodeLevel1 : INode<INodeLevel2>
    {
    }

    interface INodeLevel2 : INode<INodeLevel3>
    {
    }

    interface INodeLevel3
    { 
    }

    class NodeLevel1 : INodeLevel1
    {
        public ICollection<INodeLevel2> Children
        {
            get { throw new NotImplementedException(); }
        }
    }

    class NodeLevel2 : INodeLevel2
    {
        public ICollection<INodeLevel3> Children
        {
            get { throw new NotImplementedException(); }
        }
    }

    class NodeLevel3 : INodeLevel3
    {
    }

    class Test
    {
        void Foo()
        {
            var nodeLevel3 = new NodeLevel3();

            var nodeLevel2 = new NodeLevel2();
            nodeLevel2.Children.Add(nodeLevel3);

            var nodeLevel1 = new NodeLevel1();
            nodeLevel1.Children.Add(nodeLevel2);
        }
    }

Использование упрощается.

З.Ы. Топикстартеру — children.
Re[3]: Типизация одного уровня дерева
От: kometa_triatlon  
Дата: 14.07.09 08:21
Оценка:
+1
Но в любом случае, нужно знать максимальную глубину дерева.
Впрочем, судя по постановке задачи, это условие выполняется.
Если же типизация нужна только до определенного уровня, то можно сделать так:

interface INode<T>
{
    ICollection<T> Children { get; }
}

    interface INodeLevel1 : INode<INodeLevel2>
    {
    }

    interface INodeLevel2 : INode<INodeLevel3>
    {
    }

    interface INodeLevelAny
    {
        ICollection<INodeLevelAny> Children { get; }
    }


Тогда можно строить бесконечные деревья
Re[4]: Типизация одного уровня дерева
От: kometa_triatlon  
Дата: 14.07.09 08:23
Оценка:
Тьфу, ошибся немного...

interface INode<T>
{
    ICollection<T> Children { get; }
}

    interface INodeLevel1 : INode<INodeLevel2>
    {
    }

    interface INodeLevel2 : INode<INodeLevelAny>
    {
    }

    interface INodeLevelAny
    {
        ICollection<INodeLevelAny> Children { get; }
    }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.