Вопрос

У меня есть класс, контейнерu003CT> , который имеет контейнерыu003CT> Анкет Контейнер на самом деле принимает контейнер с двумя параметрами ограничения типаu003CTContainer,TContents> - Tcontainer - это тип контейнера, а Tcontents - это тип содержания, который он принимает.

Я хочу убедиться, что если Tcontainer был x или получен из x, то Tcontents также будут x или будут получены из x, но что Tcontents не должны равняться Tcontainer.

Я пытаюсь выразить следующие вещи.

  • Вещи, которые можно носить с собой (добыча), как карандаш.
  • Вещи, которые не могут быть перенесены (baseObject), как дерево.
  • Вещи, которые могут держать другие вещи (контейнер)
  • Контейнеры, которые не могут быть перенесены, как банк -хранилище.
  • Красивые контейнеры (как рюкзак).

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

Я хочу иметь возможность кодировать:

  • var ringWorld = new Container<BigRing, CivicWork>();
  • var pickleKnox = new Container<BankVault, Pickle>();
  • var swagBag = new Container<ToteBag, Swag>();
  • var tomeBag = new Container<ToteBag, Book>();

но нет var treeBag = new Container<Bag, Tree>();

Вот моя скелетная установка.

public abstract class BaseObject
{
    private readonly string _name;

    protected BaseObject(string name)
    {
        _name = name;
    }

    public string Name { get { return _name; } }
}
public class Swag : BaseObject
{
    private readonly int _weight;

    public Swag(string name, int weight):base(name)
    {
        _weight = weight;
    }

    public int Weight { get { return _weight; } }
}
/* I like the flexibility of i.e.: Container<BankVault,Pickles> 
but if the container itself is carriable (Swag), then its contents 
are by nature also carriable. */

public class Container<TContainer,TContents> : BaseObject 
    where TContainer:BaseObject 
    where TContents:BaseObject, or Swag if TContainer:(Swag or derived from Swag)
{
    ContainerContents<TContents> _contents;

    public Container(string name, int maxItems):base(name)
    {

        /* if (TContainer is derived from Swag) { TContents must be too } */

        _contents = new ContainerContents<TContents>(maxItems);
    }
}
public class ContainerContents<T> : List<T> where T : BaseObject
{
    int _maxItems;

    public ContainerContents(int maxItems)
    {
        _maxItems = maxItems;
    }
}
Это было полезно?

Решение

Я не думаю, что это сработает.

Я бы создал следующие интерфейсы:

interface ICarryable { }
interface IContainer<T> { }

Затем вы можете внедрить следующие классы:

class Backpack<T> : ICarryable, IContainer<T>
where T : ICarryable 
{  }

class Vault<T> : IContainer<T>
{  }

Если класс реализует ICarryable, это может быть перенесено. Если он не реализует этот интерфейс, это фиксированный объект, который нельзя перенести. Это описывает точнее, что происходит. Ваш общий Container Класс не общается, что контейнер имеет тип TContainer и его содержимое типа TContainerContents.

Чтобы не нарушать Сухой принцип, вы все еще можете создать общий базовый класс контейнеров, ваше хранилище и рюкзак наследу. Сделать его абстрактным, что никто не использует его вместо ваших конкретных реализаций.

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