C#實(shí)現(xiàn)子類(lèi)與父類(lèi)的相互轉(zhuǎn)換
子類(lèi)與父類(lèi)的相互轉(zhuǎn)換
1.父類(lèi)不能直接強(qiáng)制轉(zhuǎn)換成子類(lèi)
2.子類(lèi)可以強(qiáng)制轉(zhuǎn)換成父類(lèi),但是在父類(lèi)中只能取父類(lèi)的字段與方法因此在一個(gè)父類(lèi)對(duì)應(yīng)多個(gè)子類(lèi)的時(shí)候,不知道具體是哪個(gè)子類(lèi)的時(shí)候,就可以先聲明一個(gè)父類(lèi)的類(lèi)型。(如例1)
3.由1,2知,父類(lèi)不能直接強(qiáng)制轉(zhuǎn)換成子類(lèi),但是可以通過(guò)間接的方法進(jìn)行轉(zhuǎn)換,例1中有所體現(xiàn):將子類(lèi)轉(zhuǎn)換成父類(lèi),然后再把父類(lèi)轉(zhuǎn)換成子類(lèi),如例2。
特別說(shuō)明:雖然可以通過(guò)間接方式將父類(lèi)轉(zhuǎn)成子類(lèi),但實(shí)際用處不大,因?yàn)樾枰粋€(gè)臨時(shí)的子類(lèi)來(lái)進(jìn)行轉(zhuǎn)換,因?yàn)槠鋵?shí)可以直接在子類(lèi)直接轉(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),因此先用父類(lèi)來(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); //子類(lèi)可以強(qiáng)制轉(zhuǎn)換成父類(lèi),即裝箱
sL.Add(cs2);
for (int i = 0; i < 2;i++ )
{
//這里需要把父類(lèi)再?gòu)?qiáng)制轉(zhuǎn)換成子類(lèi)(因?yàn)槭茄b箱而來(lái)的父類(lèi),可以對(duì)其進(jìn)行拆箱成子類(lèi))
//取出子類(lè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;
//設(shè)置一個(gè)臨時(shí)的子類(lèi)
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;
}
}
} 子類(lèi)父類(lèi)之間相互轉(zhuǎn)換的問(wèn)題
為了方便演示,這里一共有兩個(gè)簡(jiǎn)單的類(lèi)
父類(lèi):動(dòng)物類(lèi)(Animal)
/// <summary>
/// 動(dòng)物類(lèi)-父類(lèi)
/// </summary>
public class Animal
{
/// <summary>
/// 腳
/// </summary>
public string Foot { get; set; }
/// <summary>
/// 頭
/// </summary>
public string Head { get; set; }
}子類(lèi):狗類(lèi)(Dog)
/// <summary>
/// 狗類(lèi)-繼承動(dòng)物類(lèi)
/// </summary>
public class Dog : Animal
{
/// <summary>
/// 尾巴
/// </summary>
public string Tail { get; set; }
/// <summary>
/// 構(gòu)造函數(shù)
/// </summary>
public Dog()
{
Head = "狗頭";
Foot = "狗腿";
Tail = "狗尾巴";
}
}第一步:如果我們將Dog類(lèi)轉(zhuǎn)換為Animal類(lèi)
Dog dog = new Dog(); //轉(zhuǎn)換為動(dòng)物類(lèi)---子類(lèi)轉(zhuǎn)換為父類(lèi) Animal animal = dog as Animal;
這個(gè)按照我們一貫的想法,應(yīng)該就是舍去子類(lèi)的擴(kuò)展屬性(這里是Tail),只保留父類(lèi)中的屬性(Foot,Head)。那么結(jié)果轉(zhuǎn)換后的Animal類(lèi)應(yīng)該這樣的

第二步:而如果我們繼續(xù)把這個(gè)對(duì)象重新轉(zhuǎn)換為Dog類(lèi) Dog dog2 = animal as Dog; Dog類(lèi)應(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類(lèi)中Tail并不是NULL

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

很明顯,父類(lèi)并不能轉(zhuǎn)換成子類(lèi),雖然編譯可以通過(guò),但是運(yùn)行時(shí)會(huì)拋出System.InvalidCastException異常,當(dāng)然這里使用as關(guān)鍵詞可以避免這一異常,結(jié)果返回NULL
那么父類(lèi)怎么轉(zhuǎn)換成子類(lèi)呢?對(duì)于一些相對(duì)簡(jiǎn)單的類(lèi),我們可以通過(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類(lèi)的公共屬性
foreach (PropertyInfo item in typeof(Animal).GetProperties())
{
item.SetValue(dog, item.GetValue(animal));
}結(jié)果:

更多有關(guān)反射的內(nèi)容可以參考官方文檔
到這里結(jié)論應(yīng)該清楚了
- 子類(lèi)可以轉(zhuǎn)換為父類(lèi),并且子類(lèi)中的擴(kuò)展屬性會(huì)被父類(lèi)“隱性”保留,但不可訪問(wèn)(編譯出錯(cuò)),以便父類(lèi)重新轉(zhuǎn)換為子類(lèi)。
- 父類(lèi)不可轉(zhuǎn)為子類(lèi),這里倒是很好理解,畢竟多變少可以,少變多就不行了。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#實(shí)現(xiàn)的ZPL條碼打印類(lèi)完整實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)的ZPL條碼打印類(lèi),結(jié)合實(shí)例形式詳細(xì)分析了C#實(shí)現(xiàn)條碼打印的原理與使用方法,代碼注釋中備有詳盡的說(shuō)明,便于理解使用,需要的朋友可以參考下2016-06-06
C#實(shí)現(xiàn)獲取計(jì)算機(jī)信息的示例代碼
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)獲取計(jì)算機(jī)軟硬件信息的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2024-01-01
用Newtonsoft將json串轉(zhuǎn)為對(duì)象的方法(詳解)
下面小編就為大家?guī)?lái)一篇用Newtonsoft將json串轉(zhuǎn)為對(duì)象的方法(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
C#使用NPOI實(shí)現(xiàn)將表格中數(shù)據(jù)導(dǎo)入Excel
NPOI是.NET版本的POI,可以幫助我們?cè)跊](méi)有安裝Microsoft Office的情況下讀寫(xiě)Office文件,下面我們就來(lái)看看C#如何使用NPOI實(shí)現(xiàn)將表格中數(shù)據(jù)導(dǎo)入Excel吧2025-02-02
一文搞懂C#實(shí)現(xiàn)讀寫(xiě)文本文件中的數(shù)據(jù)
這篇文章重點(diǎn)給大家介紹C#實(shí)現(xiàn)讀寫(xiě)文本文件中的數(shù)據(jù)的一些知識(shí),讀取.txt文件數(shù)據(jù)的實(shí)例代碼及寫(xiě)入讀取過(guò)程完整代碼,感興趣的朋友跟隨小編一起看看吧2021-06-06

