是否可以將一個對象從一個基礎轉換爲派生的對象?例如,假設我有一個基礎對象:Animal
。由此我派生出了其他幾個類:Cat
,Dog
。 現在我需要一個Animal
,但此時的類型並不重要。所以,從基地鑄造?
Animal blankCanvas = new Animal();
一路上我改變主意了,現在想的是Animal
更改爲Dog
。但是,我不明白我會怎麼做。我知道從動物轉換爲狗的業務規則,但我不知道如何實施。
是否可以將一個對象從一個基礎轉換爲派生的對象?例如,假設我有一個基礎對象:Animal
。由此我派生出了其他幾個類:Cat
,Dog
。 現在我需要一個Animal
,但此時的類型並不重要。所以,從基地鑄造?
Animal blankCanvas = new Animal();
一路上我改變主意了,現在想的是Animal
更改爲Dog
。但是,我不明白我會怎麼做。我知道從動物轉換爲狗的業務規則,但我不知道如何實施。
如果不編寫自定義轉換,則無法執行此操作。也許更好的做法是更早地決定你需要的派生類型,並創建它的一個實例。
大多數情況下,類型系統將以這種方式與您戰鬥時,您需要重新設計您的架構。
-1您無法編寫從基礎到派生類型的自定義轉換。換句話說,這不會編譯:class Derived:Base {public static explicit operator Derived(Base b){return new Derived(); }}`給出錯誤「用戶定義的轉換到基類或從基類不被允許」。 – phoog 2011-12-13 20:22:26
@phoog:這只是表達自定義轉換的一種方式。還有很多其他方式可以做到完全合法。 – 2011-12-13 22:25:28
除非您編輯您的答案,否則我無法刪除我的投票;如果你這樣做,我會的。 – phoog 2011-12-14 14:25:01
是的,您可以將基礎引用強制轉換爲派生參考。
但你似乎想要轉換一個實例。這不是鑄造,也不是直接可能的。
你的邏輯應該是這樣的,你應該知道你在創建時想要什麼類型。
下可能意義:
Animal blankCanvas = null;
...
blankCanvas = new Dog();
爲了幫助您保持正確的路徑,動物定義爲abstract class
畢竟,這是什麼的Animal
一個實例代表什麼?
據我知道你不能做到這一點與鑄造,但你可以在犬構造,將接受和動物作爲這樣的參數:
Public Dog(Animal pAnimal)
{
//do stuff...
}
你的類的實例一旦「以動物的形式出生」將以其生命爲Animal
。您可以嘗試將其轉換爲派生類,但由於實例本身仍爲Animal
,因此在所有情況下都會失敗。
這裏有一些建議,你怎麼可以把它改成其他類:
您可以通過顯式使用一個靜態方法實現它實現自定義轉換到另一個類,例如,可以實現類似:
public class Cat : Animal
{
public Cat FromAnimal(Animal animal)
{
return new Cat(animal) {Eyes = Color.Blue, ... };
}
}
您可以使用支持反序列化的某些序列化器在另一個類中序列化並反序列化您的實例。
您可以使用派生類型的顯式返回類型實現實例的深度克隆。
然後,您只需將您的舊Animal
替換爲新的Cat
並在任何地方使用......
您可以在這樣的派生類中使用靜態方法:
/// <summary>
/// Dog.
/// </summary>
class Dog : Animal
{
/// <summary>
/// Initializes a new instance of the <see cref="Dog"/> class.
/// </summary>
/// <param name="type">The type.</param>
public Dog(string type)
: base(type)
{ }
/// <summary>
/// Gets a dog from an animal.
/// </summary>
/// <param name="animal">The animal.</param>
/// <returns></returns>
public static Dog FromAnimal(Animal animal)
{
return new Dog(animal.Type);
}
}
/// <summary>
/// Animal.
/// </summary>
class Animal
{
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public string Type { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="Animal"/> class.
/// </summary>
/// <param name="type">The type.</param>
public Animal(string type)
{
this.Type = type;
}
}
或者使用一個工廠類來管理所有你需要的轉換。
當你試過這個時會發生什麼?創建一個具有2個類的動物和狗的控制檯應用程序。讓它們不同以至於你可以清楚地看到正在使用哪個並嘗試投射。如果/當你遇到錯誤,發佈它們。 – taylonr 2011-12-13 20:13:04