Лить дочерний объект как родителя - программирование
Подтвердить что ты не робот

Лить дочерний объект как родителя

Мне нужно уметь экземпляр дочернего объекта экземпляру родительского объекта.

public class Parent 
{
 public string name{get;set;} 
}

public class Child : Parent{}

var myClass = new Child()
(Parent)myClass
//this doesnt seem to work and the object still has childs type.

есть ли другой способ сделать это?

спасибо

4b9b3361

Ответ 1

Проблема - сериализатор xml сериализует объект с типом child как корневой элемент. Я действительно не хочу передавать свой целевой тип полностью вниз в сериализатор. Есть ли способ лучше? - Жюль

Я много не работал с сериализацией, но думаю, вам придется изменить свое определение "как я сериализую себя" в дочернем элементе, чтобы написать себя, как если бы это был родитель.

Если вы действительно хотите иметь экземпляр "Родитель", вам нужно создать нового родителя и скопировать все значения из Ребенка в этот родитель. (Я бы не сделал этого, если у вас их много, но если у вас их нет, это не должно быть проблемой.) Самый простой способ сделать это - создать конструктор копирования в Parent. Это был бы конструктор, который принимает Parent как параметр и копирует значения (Name в этом случае, и я предполагаю, что вы, возможно, опустили другие), от параметра к себе. Затем вы можете создать нового родителя, передать его в качестве параметра (поскольку ребенок является родителем, не требуется преобразование/преобразование), и он выплюнет фактический экземпляр родителя.

Ответ 2

Вы не назначаете приведение к чему-либо.

var myClass = new Child();
Parent p = (Parent)myClass;

Изменить. Я думаю, вы неправильно поняли, как работает кастинг. У Say Parent есть метод virtual, DoStuff(). который переопределяется в Child. Даже если вы отбрасываете myClass в Parent, он запускает метод Child DoStuff. Независимо от того, что Child является Child и всегда будет Child, даже если вы его произнесли.

Если вы пытаетесь передать его методу, который принимает объект Parent, вам не нужно его использовать. Он уже a Parent, благодаря a Child.

Я думаю, что мы чего-то не замечаем. Что вы пытаетесь совершить? Что не работает?

Ответ 3

Это должно работать.

Но я подозреваю, что вы написали свой код, что вы не захватили объект cast в новой переменной? Попробуйте следующее:

var myClass = new Child()
var myClassAsParent = (Parent)myClass;
// myClassAsParent still has the type "Child", but can be accessed as if it were a Parent.

Edit Основываясь на некоторых комментариях, которые вы оставили, я считаю, что вы неправильно понимаете фундаментальный аспект большинства языков программирования. Это так: Тип объекта не может измениться. Объект, который был создан как объект Child, всегда будет объектом Child.

Кастинг не меняет тип объекта. Кастинг изменяет способ, которым остальная часть программы "видит" объект. Он изменяет интерфейс объекта, если хотите. Поэтому, если вы добавили объект Child к типу Parent, остальная часть программы считает, что он имеет дело с типом Parent, но он действительно имеет дело с типом Child, который заключается в использовании действительно плохой аналогии, одетый в свою родительскую одежду.

Короче говоря, Кастинг не делает того, что вы думаете.

Ответ 4

вы можете использовать оператор as... хорошая вещь о THAT не является исключением, и вы можете проверить значение null, если "cast" терпит неудачу.

public class Parent 
{
 public string name{get;set;} 
}

public class child : Parent{}

var myClass = new Child()
Parent foo  = myClass as Parent
if ( foo == null ) Debug.WriteLine("foo is NOT of type Parent");

Ответ 5

Если Parent является суперклассом Child, тогда автоматически a Child также является Parent (содержит все свойства и методы "Parent" ), и вам не нужно делать бросок.

Кроме того, вы не можете просто запустить строку с литой. Например, вы можете написать

Parent p = (Parent)myClass;

Ответ 6

Просто ударив вариант проблемы, я думаю, что у меня есть решение, не основанное на сериализации.

Как и у OP, у меня есть класс B, который наследуется от класса A, и мне нужно B.GetType(). Имя для возврата, как если бы это был класс A.

В классе B вам нужно переопределить GetType() для возврата .GetType(). BaseType

Таким образом, B.GetType() всегда будет выглядеть как A.GetType()

Как это довольно тяжело, и все мои классы наследуют от моего собственного стандартного baseClass, я собираюсь добавить свойство, называемое TypeName, в baseClass, которое возвращает this.GetType(). Name

Затем на моем одном специальном классе, который должен выглядеть как родительский, я переопределю его, чтобы вернуть this.GetType(). BaseType.Name

Затем в моем коде я буду ссылаться на .TypeName вместо того, чтобы делать .GetType(). Имя непосредственно, когда мне нужно специальное "маскирование" имени типа класса, которое нужно использовать. Учитывая, что я использую только .GetType() в той области, где мне нужно игнорировать этот дочерний класс, он достаточно чист для моего собственного использования.

Ответ 7

У меня была та же проблема и вышло следующее решение:

Мой исходный код был таким образом:

public class Person
{
    public string Name { get; set; }

    public Person() {};
    public Person( Person rhs ) 
    {
        Name = rhs.Name;
    }
}

public class Customer : Person
{
    private string m_role = "Customer";
    public string Role { get m_role; }

    public Customer() : base();
}

public class Employee : Person
{
    private string m_role = "Employee";
    public string Role { get m_role; }

    public Customer() : base();
}

и когда я попробовал лить объект Person клиенту, я получил ошибки "сбой"

Вместо того, чтобы преследовать идею кастинга, я решил изменить конструкторы Child copy, таким образом:

public class Customer : Person
{
    private string m_role = "Customer";
    public string Role { get m_role; }

    public Customer() : base();
    public Customer( Person per ) : base( per);
}

public class Employee : Person
{
    private string m_role = "Employee";
    public string Role { get m_role; }

    public Employee () : base();
    public Employee ( Person per) : base( per);
}

Ответ 8

Мне около пяти лет здесь, но...

Вы можете использовать AutoMapper, чтобы решить вашу проблему.

Просто определите сопоставление между родительским и дочерним классами. Простейшая карта будет делать. В классе, где вы определяете свои сопоставления:

CreateMap<Child, Parent>();

Затем в любой точке вашего кода вы можете сделать:

Child child = new Child();
Parent parent = Mapper.Map<Parent>(child);

И ваш объект parent будет чистым parent без каких-либо свойств объекта child.

Как говорили другие, бросание объекта будет сохранять его тип. Это только изменяет указатель. Но AutoMapper создает новый экземпляр целевого типа и копирует значения из этого параметра в экземпляр целевого типа, сопоставляя свойства по имени.