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)換成子類,但是可以通過間接的方法進(jìn)行轉(zhuǎn)換,例1中有所體現(xiàn):將子類轉(zhuǎn)換成父類,然后再把父類轉(zhuǎn)換成子類,如例2。
特別說明:雖然可以通過間接方式將父類轉(zhuǎn)成子類,但實(shí)際用處不大,因?yàn)樾枰粋€(gè)臨時(shí)的子類來進(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è)子類,因此先用父類來聲明
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箱而來的父類,可以對(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)換的問題
為了方便演示,這里一共有兩個(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沒有把Tail這個(gè)字段拋去,如下圖

但是,在VS的智能提示中我們并不能訪問Tail屬性,直接使用編譯也會(huì)報(bào)錯(cuò)

而且從上面的結(jié)果中,我們也能猜出第二步的實(shí)際結(jié)果,Dog類中Tail并不是NULL

第三步:試試父類轉(zhuǎn)換為子類

很明顯,父類并不能轉(zhuǎn)換成子類,雖然編譯可以通過,但是運(yùn)行時(shí)會(huì)拋出System.InvalidCastException異常,當(dāng)然這里使用as關(guān)鍵詞可以避免這一異常,結(jié)果返回NULL
那么父類怎么轉(zhuǎn)換成子類呢?對(duì)于一些相對(duì)簡(jiǎn)單的類,我們可以通過遍歷的方式逐個(gè)賦值
Animal animal = new Animal
{
Foot = "腳",
Head = "頭"
};
Dog dog = new Dog
{
Foot = animal.Foot,
Head = animal.Head,
};如果屬性多的時(shí)候,使用這種方法就麻煩了,這時(shí)可以使用反射遍歷屬性來設(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ì)被父類“隱性”保留,但不可訪問(編譯出錯(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-10
c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn),需要的朋友可以參考下2014-02-02
C#簡(jiǎn)單多線程同步和優(yōu)先權(quán)用法實(shí)例
這篇文章主要介紹了C#簡(jiǎn)單多線程同步和優(yōu)先權(quán)用法實(shí)例,對(duì)于C#線程的阻塞、同步、異步、互斥等概念做了較為深入的分析與實(shí)例講解,需要的朋友可以參考下2014-09-09
C#中DataTable 轉(zhuǎn)實(shí)體實(shí)例詳解
這篇文章主要介紹了C#中DataTable 轉(zhuǎn)實(shí)體實(shí)例詳解,需要的朋友可以參考下2017-04-04

