Как превратить экземпляр животного в экземпляр собаки?
скажем, у меня есть следующие классы:
class Animal
{
public long Id { get; set; }
public string Name { get; set; }
}
class Dog:Animal
{
public void sniffBum()
{
Console.WriteLine("sniff sniff sniff");
}
}
если у меня есть экземпляр Animal
, как мне бросить его в Dog
?
Что-то вроде этого:--10-->
Animal a = new Animal();
if ( some logic to determine that this animal is a dog )
{
Dog d = (Dog)a;
d.sniffBum();
}
по сути, я не могу использовать интерфейсы. У меня всегда будет Animal
объект выходит из моей базы данных, как это. Dog
не имеет больше параметров, чем Animal
имеет, только новые методы.
я мог бы просто создать новый Dog
object и передать значения через (или иметь конструктор, который принимает тип Animal
), но это только кажется грязным.
10 ответов
проверка кастинга не будет работать, если Animal
экземпляр никогда не был Dog
экземпляра.
вы можете посмотреть на Шаблон "Декоратор", что позволит вам добавить Dog
методы Animal
экземпляра. По существу,Dog
и Animal
как есть IAnimal
интерфейс. The Dog
класс берет Animal
экземпляра в конструкторе и сохраняет внутреннюю ссылку. The Dog
' s IAnimal
реализация просто откладывается на Animal
экземпляр он ссылается (что позволяет Dog
быть брошенным в IAnimal
и вести себя как завернутый Animal
полиморфизм). The Dog
также имеет дополнительные методы, специфичные для собак.
сначала создайте животное как собаку, затем проверьте, если это is
собака
Animal a = new Dog();
if (a is Dog )
{
Dog d = (Dog)a;
d.sniffBum();
}
чтобы проверить, может ли объект быть приведен к типу, используйте is
ключевое слово.
Animal animal = new Dog();
if( animal is Dog)
{
//your code
}
С is
, но так как вы хотите что-то назвать на любых собаках, которые вы найдете, было бы лучше использовать as
:
var dog = a as Dog;
if (dog != null)
{
dog.sniffButt();
}
однако вы должны знать, что это расположение (попытка определить тип времени выполнения значения, чтобы вы могли привести его к чему-то удобному) обычно неодобрительно относится к уважительной причине. Вы можете легко перестараться и в конечном итоге проверить собак, кошек, попугаев, рыб, черепах... Я уверен, что вы можете визуализировать результат беспорядок.
Если ваши потребности указывают на то, что сценарий, лучшим решением является использование шаблона разработки посетителя.
животное никогда не может быть собакой.
сделайте свой конструктор собаки, принимая животное в качестве параметра.
class Dog : Animal
{
public Dog(Animal a)
{
this.Name = a.Name;
this.Id = a.Id;
}
public void sniffBum()
{
Console.WriteLine("sniff sniff sniff");
}
}
Я так не работаю. Кастинг-это операция, которая интерпретирует экземпляр как данный тип, он не будет изменить его тип. В вашем случае вы должны сначала определить, какое животное есть в этой конкретной строке базы данных, а затем создать экземпляр правильного предка. Псевдокод:
var row = Fetch from database;
Animal animal;
if (row is a dog) animal = new Dog();
else if (row is a cat) animal = new Cat();
вы можете сделать это:
var dog = a as Dog;
if(dog != null)
{
dog.DoSomething();
}
это preffereable для проверки, если собака, Если вам нужно бросить его последний. См. следующий ответ: кастинг против использования ключевого слова " as " в CLR
вы не можете разыграть животное, в собаку, это может быть кошка! Я думаю, что вы пытаетесь достичь, чтобы создать объект типа Dog
, от другого объекта типа Animal
Это было извлечено из db.
один из способов-принять объект типа Animal
на Dog
перегруженный конструктор:
class Dog:Animal
{
public Dog(Animal animal)
{
this.Id = animal.Id;
this.Name = animal.Name;
}
...
}
таким образом, вы можете просто использовать следующее:
if ( some logic to determine that this animal is a dog )
{
Dog d = new Dog(a);
d.sniffBum();
}
Камьяр прав, нет никакого способа сделать это, потому что, как вы сами сказали нам
i will always have an Animal object coming out of my database like that
поэтому вам нужно сохранить тип также в вашей базе данных
после этого вы должны изменить свой Animal
to
public class Animal
{
public long Id { get; set; }
public string Name { get; set; }
public string AnimalType { get; private set; }
public Animal() { }
public Animal(string type)
{
AnimalType = type;
}
// to denie self repeading if all animales have the same Properties
protected void set(Animal a)
{
Id = a.Id;
Name = a.Name;
AnimalType = a.AnimalType;
}
}
.
Dog doesnt have any more parameters than Animal has, only new methods
так что вы можете modifie свой Dog
to
public class Dog : Animal
{
public Dog(Animal a)
{
base.set(a);
}
public void sniffBum()
{
Console.WriteLine("sniff sniff sniff");
}
}
.
i could just create a new Dog object, and pass the values accross, (...), but this just seems messy
Я не думаю, что есть способ обойти и это не выглядит так неопрятно
а вот как использовать пример
Animal a = new Animal("Dog");
if (a.AnimalType =="Dog")
{
Dog d = new Dog( a);
d.sniffBum();
}