首頁 > 軟體

C#實現子類與父類別的相互轉換

2022-05-21 13:01:45

子類與父類別的相互轉換

1.父類別不能直接強制轉換成子類

2.子類可以強制轉換成父類別,但是在父類別中只能取父類別的欄位與方法因此在一個父類別對應多個子類的時候,不知道具體是哪個子類的時候,就可以先宣告一個父類別的型別。(如例1)

3.由1,2知,父類別不能直接強制轉換成子類,但是可以通過間接的方法進行轉換,例1中有所體現:將子類轉換成父類別,然後再把父類別轉換成子類,如例2。

特別說明:雖然可以通過間接方式將父類別轉成子類,但實際用處不大,因為需要一個臨時的子類來進行轉換,因為其實可以直接在子類直接轉換,所以實際用處不大。

(下例只適用於從棧制到堆的行為,即裝箱拆箱)

例一

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
namespace testApplication  
{  
 public class Parent  
    {  
        public int a=0;  
    }  
    public class Son:Parent  
    {  
        public int b=0;  
        public int run()  
        {  
            return a + b;  
        }  
    }  
    public class Son2 : Parent  
    {  
        public string c = "Son2";  
        public int run()  
        {  
            return a;  
        }  
    }  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            //不知道具體是哪個子類,因此先用父類別來宣告  
            List<Parent> sL = new List<Parent>();  
            Son cs1 = new Son(); cs1.b = -1;  
            Son cs2 = new Son(); cs2.b = -2;  
            sL.Add(cs1);  //子類可以強制轉換成父類別,即裝箱 
            sL.Add(cs2);  
            for (int i = 0; i < 2;i++ )  
            {  
                //這裡需要把父類別再強制轉換成子類(因為是裝箱而來的父類別,可以對其進行拆箱成子類)  
                //取出子類中的欄位,即拆箱  
                Console.WriteLine(((Son)sL[i]).b);  
            }  
            Console.ReadLine();  
        }  
    }  
}  

例二

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
namespace testApplication  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Parent pa = new Parent();  
            pa.a=9;  
            //設定一個臨時的子類  
            Son tmpt = new Son();  
            tmpt.a = 9;  
            //進行裝箱  
            pa = (Parent)tmpt;  
            //進行拆箱  
            Son cson = (Son)pa;  
            Console.WriteLine(cson.a);  
            Console.ReadLine();  
        }  
    }  
    public class Parent  
    {  
        public int a=0;  
    }  
    public class Son:Parent  
    {  
        public int b=0;  
        public int run()  
        {  
            return a + b;  
        }  
    }  
    public class Son2 : Parent  
    {  
        public string c = "Son2";  
        public int run()  
        {  
            return a;  
        }  
    }  
}  

子類父類別之間相互轉換的問題

為了方便演示,這裡一共有兩個簡單的類

父類別:動物類(Animal)

/// <summary>
/// 動物類-父類別
/// </summary>
public class Animal
{
    /// <summary>
    /// 腳
    /// </summary>
    public string Foot { get; set; }
    /// <summary>
    /// 頭
    /// </summary>
    public string Head { get; set; }
}

子類:狗類(Dog)

/// <summary>
/// 狗類-繼承動物類
/// </summary>
public class Dog : Animal
{
    /// <summary>
    /// 尾巴
    /// </summary>
    public string Tail { get; set; }
    /// <summary>
    /// 建構函式
    /// </summary>
    public Dog()
    {
        Head = "狗頭";
        Foot = "狗腿";
        Tail = "狗尾巴";
    }
}

第一步:如果我們將Dog類轉換為Animal類

Dog dog = new Dog();
//轉換為動物類---子類轉換為父類別
Animal animal = dog as Animal;

這個按照我們一貫的想法,應該就是捨去子類的擴充套件屬性(這裡是Tail),只保留父類別中的屬性(Foot,Head)。那麼結果轉換後的Animal類應該這樣的

第二步:而如果我們繼續把這個物件重新轉換為Dog類 Dog dog2 = animal as Dog; Dog類應該是這樣的

但是事實上,在第一步把Dog轉換為Animal時,Animal沒有把Tail這個欄位拋去,如下圖

但是,在VS的智慧提示中我們並不能存取Tail屬性,直接使用編譯也會報錯

而且從上面的結果中,我們也能猜出第二步的實際結果,Dog類中Tail並不是NULL

第三步:試試父類別轉換為子類

很明顯,父類別並不能轉換成子類,雖然編譯可以通過,但是執行時會丟擲System.InvalidCastException異常,當然這裡使用as關鍵詞可以避免這一異常,結果返回NULL

那麼父類別怎麼轉換成子類呢?對於一些相對簡單的類,我們可以通過遍歷的方式逐個賦值

Animal animal = new Animal
{
    Foot = "腳",
    Head = "頭"
};
Dog dog = new Dog
{
    Foot = animal.Foot,
    Head = animal.Head,
};

如果屬性多的時候,使用這種方法就麻煩了,這時可以使用反射遍歷屬性來設定對應的值

Animal animal = new Animal
{
    Foot = "腳",
    Head = "頭"
};
Dog dog = new Dog();
//遍歷Animal類的公共屬性
foreach (PropertyInfo item in typeof(Animal).GetProperties())
{
    item.SetValue(dog, item.GetValue(animal));
}

結果:

更多有關反射的內容可以參考官方檔案

到這裡結論應該清楚了

  • 子類可以轉換為父類別,並且子類中的擴充套件屬性會被父類別“隱性”保留,但不可存取(編譯出錯),以便父類別重新轉換為子類。
  • 父類別不可轉為子類,這裡倒是很好理解,畢竟多變少可以,少變多就不行了。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com