C#實(shí)現(xiàn)子類與父類的相互轉(zhuǎn)換
子類與父類的相互轉(zhuǎn)換
1.父類不能直接強(qiáng)制轉(zhuǎn)換成子類
2.子類可以強(qiáng)制轉(zhuǎn)換成父類,但是在父類中只能取父類的字段與方法因此在一個(gè)父類對(duì)應(yīng)多個(gè)子類的時(shí)候,不知道具體是哪個(gè)子類的時(shí)候,就可以先聲明一個(gè)父類的類型。(如例1)
3.由1,2知,父類不能直接強(qiáng)制轉(zhuǎn)換成子類,但是可以通過(guò)間接的方法進(jìn)行轉(zhuǎn)換,例1中有所體現(xiàn):將子類轉(zhuǎn)換成父類,然后再把父類轉(zhuǎn)換成子類,如例2。
特別說(shuō)明:雖然可以通過(guò)間接方式將父類轉(zhuǎn)成子類,但實(shí)際用處不大,因?yàn)樾枰粋€(gè)臨時(shí)的子類來(lái)進(jìn)行轉(zhuǎn)換,因?yàn)槠鋵?shí)可以直接在子類直接轉(zhuǎn)換,所以實(shí)際用處不大。
(下例只適用于從棧制到堆的行為,即裝箱拆箱)
例一
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) { //不知道具體是哪個(gè)子類,因此先用父類來(lái)聲明 List<Parent> sL = new List<Parent>(); Son cs1 = new Son(); cs1.b = -1; Son cs2 = new Son(); cs2.b = -2; sL.Add(cs1); //子類可以強(qiáng)制轉(zhuǎn)換成父類,即裝箱 sL.Add(cs2); for (int i = 0; i < 2;i++ ) { //這里需要把父類再?gòu)?qiáng)制轉(zhuǎn)換成子類(因?yàn)槭茄b箱而來(lái)的父類,可以對(duì)其進(jìn)行拆箱成子類) //取出子類中的字段,即拆箱 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; //設(shè)置一個(gè)臨時(shí)的子類 Son tmpt = new Son(); tmpt.a = 9; //進(jìn)行裝箱 pa = (Parent)tmpt; //進(jìn)行拆箱 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; } } }
子類父類之間相互轉(zhuǎn)換的問(wèn)題
為了方便演示,這里一共有兩個(gè)簡(jiǎn)單的類
父類:動(dòng)物類(Animal)
/// <summary> /// 動(dòng)物類-父類 /// </summary> public class Animal { /// <summary> /// 腳 /// </summary> public string Foot { get; set; } /// <summary> /// 頭 /// </summary> public string Head { get; set; } }
子類:狗類(Dog)
/// <summary> /// 狗類-繼承動(dòng)物類 /// </summary> public class Dog : Animal { /// <summary> /// 尾巴 /// </summary> public string Tail { get; set; } /// <summary> /// 構(gòu)造函數(shù) /// </summary> public Dog() { Head = "狗頭"; Foot = "狗腿"; Tail = "狗尾巴"; } }
第一步:如果我們將Dog類轉(zhuǎn)換為Animal類
Dog dog = new Dog(); //轉(zhuǎn)換為動(dòng)物類---子類轉(zhuǎn)換為父類 Animal animal = dog as Animal;
這個(gè)按照我們一貫的想法,應(yīng)該就是舍去子類的擴(kuò)展屬性(這里是Tail),只保留父類中的屬性(Foot,Head)。那么結(jié)果轉(zhuǎn)換后的Animal類應(yīng)該這樣的
第二步:而如果我們繼續(xù)把這個(gè)對(duì)象重新轉(zhuǎn)換為Dog類 Dog dog2 = animal as Dog; Dog類應(yīng)該是這樣的
但是事實(shí)上,在第一步把Dog轉(zhuǎn)換為Animal時(shí),Animal沒(méi)有把Tail這個(gè)字段拋去,如下圖
但是,在VS的智能提示中我們并不能訪問(wèn)Tail屬性,直接使用編譯也會(huì)報(bào)錯(cuò)
而且從上面的結(jié)果中,我們也能猜出第二步的實(shí)際結(jié)果,Dog類中Tail并不是NULL
第三步:試試父類轉(zhuǎn)換為子類
很明顯,父類并不能轉(zhuǎn)換成子類,雖然編譯可以通過(guò),但是運(yùn)行時(shí)會(huì)拋出System.InvalidCastException異常,當(dāng)然這里使用as關(guān)鍵詞可以避免這一異常,結(jié)果返回NULL
那么父類怎么轉(zhuǎn)換成子類呢?對(duì)于一些相對(duì)簡(jiǎn)單的類,我們可以通過(guò)遍歷的方式逐個(gè)賦值
Animal animal = new Animal { Foot = "腳", Head = "頭" }; Dog dog = new Dog { Foot = animal.Foot, Head = animal.Head, };
如果屬性多的時(shí)候,使用這種方法就麻煩了,這時(shí)可以使用反射遍歷屬性來(lái)設(shè)置對(duì)應(yīng)的值
Animal animal = new Animal { Foot = "腳", Head = "頭" }; Dog dog = new Dog(); //遍歷Animal類的公共屬性 foreach (PropertyInfo item in typeof(Animal).GetProperties()) { item.SetValue(dog, item.GetValue(animal)); }
結(jié)果:
更多有關(guān)反射的內(nèi)容可以參考官方文檔
到這里結(jié)論應(yīng)該清楚了
- 子類可以轉(zhuǎn)換為父類,并且子類中的擴(kuò)展屬性會(huì)被父類“隱性”保留,但不可訪問(wèn)(編譯出錯(cuò)),以便父類重新轉(zhuǎn)換為子類。
- 父類不可轉(zhuǎn)為子類,這里倒是很好理解,畢竟多變少可以,少變多就不行了。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C# WinForm應(yīng)用程序降低系統(tǒng)內(nèi)存占用方法總結(jié)
這篇文章主要介紹了C# WinForm應(yīng)用程序降低系統(tǒng)內(nèi)存占用方法總結(jié),本文總結(jié)了9個(gè)方法,同時(shí)給出了一個(gè)定期清理執(zhí)行垃圾回收代碼,需要的朋友可以參考下2014-10-10c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn),需要的朋友可以參考下2014-02-02C#簡(jiǎn)單多線程同步和優(yōu)先權(quán)用法實(shí)例
這篇文章主要介紹了C#簡(jiǎn)單多線程同步和優(yōu)先權(quán)用法實(shí)例,對(duì)于C#線程的阻塞、同步、異步、互斥等概念做了較為深入的分析與實(shí)例講解,需要的朋友可以參考下2014-09-09C#中DataTable 轉(zhuǎn)實(shí)體實(shí)例詳解
這篇文章主要介紹了C#中DataTable 轉(zhuǎn)實(shí)體實(shí)例詳解,需要的朋友可以參考下2017-04-04