C # кастинг и наследование - PullRequest
       5

C # кастинг и наследование

3 голосов
/ 31 августа 2011

У меня есть объект, который я много раздаю.

Мне нужно добавить к нему часть данных, и я не могу изменить базовый класс

Так что у меня есть

static OriginalThing GetNewThing()
{
  return new OriginalThing();
}

Теперь я хочу добавить свою часть данных

class EnhancedThing : OriginalThing
{
  string name;
  static EnhancedThing GetNewThing(string name)
  {
     EnhancedThing ething = new OriginalThing();   <---doesnt work even if i cast it
     ething.Name = name;
  }
}

Как мне это сделать?

Ответы [ 4 ]

3 голосов
/ 31 августа 2011

Вы не можете назначить OriginalThing для NewThing, потому что это просто , а не a NewThing. Другой способ отлично работает, потому что NewThing способен на все, что есть OriginalThing, но обратное неверно.

Просто создайте экземпляр EnhancedThing, назначьте имя и верните его. Вы можете обращаться с EnhancedThing как с OriginalThing, поскольку является * OriginalThing.

class EnhancedThing : OriginalThing
{
  public string Name { get; private set; }
  static EnhancedThing GetNewThing(string name)
  {
     EnhanedThing thing = new EnhancedThing();
     thing.Name = name;
     return thing;
  }
}

// ...

OriginalThing foo = EnhancedThing.GetNewThing( "someName" );

Также следует понимать, что это не очень выгодно, поскольку name в настоящее время является закрытой переменной-членом (в вашем примере), и вы не сможете получить доступ к какой-либо дополнительной функциональности объектов NewThing, если не будете обращаться с ними как с NewThing с (в отличие от OriginalThings, но вы можете передать их как OriginalThing с, если необходимо)

1 голос
/ 31 августа 2011

Вам нужно сделать это:

EnhancedThing ething = new EnhancedThing();
0 голосов
/ 31 августа 2011

Если другой класс запечатан, вы можете использовать инкапсуляцию в своем новом классе, а затем изменить / расширить API. Затем вы можете определить неявное приведение от одного объекта к другому и использовать эти типы взаимозаменяемо без приведения .

Подходит ли это в вашем случае, зависит от того, что вы намереваетесь делать и чего вы пытаетесь достичь, но это ценная техника. Это более полезно для сокрытия некоторых / всех членов оригинала и переопределения API.

// no need to cast
EnhancedThing thing = new OriginalThing();
var result = thing.NewMethod();

// again no need to cast, treat as original when passing around
OriginalThing original = thing;

public class EnhancedThing
{
    private readonly OriginalThing originalThing;

    public static implicit operator OriginalThing(EnhancedThing enhancedThing)
    {
        return enhancedThing.originalThing;
    }

    public static implicit operator EnhancedThing(OriginalThing originalThing)
    {
        return new EnhancedThing(originalThing);
    }

    private EnhancedThing(OriginalThing originalThing)
    {
        this.originalThing = originalThing;
    }

    public string OriginalMethod()
    {
        return originalThing.OriginalMethod();
    }

    public string NewMethod()
    {
        var value = originalThing.OriginalMethod();
        // extra processing ...
        return value;
    }
}

Этот метод широко используется в Sitecore для предоставления моделей типов данных из общей базовой реализации. Одно предупреждение, если вы намереваетесь добавить новое поле данных, оно будет потеряно при восходящей передаче.

0 голосов
/ 31 августа 2011

Это потому, что OriginalThing - это не EnhancedThing, а EnhancedThing - это OriginalThing.

Одна вещь, которую вы могли бы сделать, это иметь конструктор для EnhancedThing, который принимает OriginalThing и копирует применяемые члены.

class EnhancedThing : OriginalThing
{
    public EnhancedThing()
    {
        // default constructor
    }

    public EnhancedThing( OriginalThing src )
    {
        // copy over the significant items
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...