[英]How to allow Class Property be of multiple/flexible types in c#?
在C#中,我有三個類:Person,Cat和Dog。
Cat和Dog類都有方法Eat()。
我希望Person類有一個屬性'Pet'。
我希望能夠通過Person之類的Person.Pet.Eat()調用Cat和Dog的Eat方法,但我不能,因為Pet屬性需要是Cat或Dog類型。
目前我正在使用Person類中的兩個屬性:PetDog和PetCat。
現在這是可以的,但如果我想要100種不同類型的動物作為寵物,那么我真的不想在Person類中擁有100種不同的Pet屬性。
有沒有辦法使用接口或繼承? 有沒有辦法可以將Pet設置為Object類型,但仍然可以訪問分配給它的動物類的屬性?
你可以讓寵物從一個共同的基類派生出來:
public abstract class Animal
{
protected Animal() { }
public abstract void Eat();
}
然后Cat和Dog派生自這個基類:
public class Cat: Animal
{
public override void Eat()
{
// TODO: Provide an implementation for an eating cat
}
}
public class Dog: Animal
{
public override void Eat()
{
// TODO: Provide an implementation for an eating dog
}
}
並且您的Person類將具有Animal
類型的屬性:
public class Person
{
public Animal Pet { get; set; }
}
當你有一個Person實例時:
var person = new Person
{
Pet = new Cat()
};
// This will call the Eat method from the Cat class as the pet is a cat
person.Pet.Eat();
您還可以為基類中的Eat
方法提供一些常見的實現,以避免在派生類中重寫它:
public abstract class Animal
{
protected Animal() { }
public virtual void Eat()
{
// TODO : Provide some common implementation for an eating animal
}
}
請注意, Animal
仍然是一個抽象類,以防止它直接實例化。
public class Cat: Animal
{
}
public class Dog: Animal
{
public override void Eat()
{
// TODO: Some specific behavior for an eating dog like
// doing a mess all around his bowl :-)
base.Eat();
}
}
有沒有辦法使用接口或繼承?
是。
接口:創建IEat或IPet接口或您想要表示的任何概念。 使界面具有Eat方法。 讓Cat和Dog實現此界面。 讓Pet屬性屬於那種類型。
繼承:創建一個抽象基類Animal或Pet或您想要表示的任何概念。 在基類上創建一個抽象方法Eat。 讓貓和狗繼承這個基類。 讓Pet屬性屬於那種類型。
這兩者有什么區別?
使用接口來模擬“X知道如何做Y”的想法。 例如,IDisposable意味着“我知道如何處置我所持有的重要資源”。 這不是關於對象是什么的事實,它是關於對象做什么的事實。
使用繼承來模擬“X是一種Y”的概念。 狗是一種動物。
關於接口的事情是你可以擁有任意數量的接口。 但是你只能直接從一個基類繼承,所以如果你要使用繼承,你必須確保你做對了。 繼承的問題是人們最終制作像“車輛”這樣的基礎類,然后他們說“一輛軍車是一種車輛”和“一艘船是一種車輛”,現在你被卡住了:什么是基礎毀滅者的類? 它既是船只又是軍用車輛, 它不能同時存在 。 非常仔細地選擇“繼承支點” 。
有沒有辦法可以將Pet設置為Object類型,但仍然可以訪問分配給它的動物類的屬性?
是的,在C#4中有,但不要這樣做 。 使用接口或繼承。
在C#4中,您可以使用“dynamic”在運行時動態調度到Pet中對象的Eat方法。
你不想這樣做的原因是因為如果有人在Pet屬性中放入Fruit或Handsaw然后嘗試將其變為Eat, 這將會崩潰並且可怕地死亡 。 編譯時檢查的目的是減少程序的脆弱性。 如果您有辦法進行更多的編譯時檢查,請使用它。
使用界面;
abstract class Animal
{
public virtual void DoSomething() { }
}
interface ICanEat
{
void Eat();
}
class Dog : Animal, ICanEat
{
public void Eat()
{
Console.Out.WriteLine("Dog eat");
}
}
class Cat : Animal, ICanEat
{
public void Eat()
{
Console.Out.WriteLine("Cat eat");
}
}
class Person
{
public Animal MyAnimal { get; set; }
}
然后你可以打電話
(person.MyAnimal as ICanEat).Eat();
在你去的時候執行正確的空值檢查。
使用抽象類。
public abstract class Pet { public abstract void Eat(); }
public class Dog : Pet { }
public class Cat : Pet { }
public class Person {
public Pet Pet;
}
我相信你可以做其余的事。
為什么不創建Pet類型的基類
public abstract class Pet{
public abstract void Eat();
}
讓這只貓和狗從接口IPet
繼承
public interface IPet
{
bool hungry();
void Eat();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.