C#实现子类与父类的相互转换

目录
  • 子类与父类的相互转换
    • 例一
    • 例二
  • 子类父类之间相互转换的问题
    • 父类:动物类(Animal)
    • 子类:狗类(Dog)

子类与父类的相互转换

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));
}

结果:

更多有关反射的内容可以参考官方文档

到这里结论应该清楚了

  • 子类可以转换为父类,并且子类中的扩展属性会被父类“隐性”保留,但不可访问(编译出错),以便父类重新转换为子类。
  • 父类不可转为子类,这里倒是很好理解,毕竟多变少可以,少变多就不行了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • c# 字段和方法设计建议

    1.不要为抽象类提供公开的构造方法 抽象类可以有构造方法,但是抽象类不能实例化.如果编程人员没有制定构造方法,编译器会自动生成一个默认的protected构造方法.下面是一个标准的简单抽象类: abstract class MyAbstractClass { protected MyAbstractClass( ) { } } 抽象类的构造方法不应该是public或internal的.抽象类设计的本意是只能让子类继承,而不是用于生成实例对象.如果抽象类是public或者internal的,它对于

  • C#中子类调用父类的实现方法

    本文实例讲述了C#中实现子类调用父类的方法,分享给大家供大家参考之用.具体方法如下: 一.通过子类无参构造函数创建子类实例 创建父类Person和子类Student. public class Person { public Person() { Console.WriteLine("我是人"); } } public class Student : Person { public Student() { Console.WriteLine("我是学生"); } }

  • C#构造函数在基类和父类中的执行顺序

    一.简介 当我们没有在子类构造函数中写上 base(),默认会先调用父类中无参的构造函数,再调用子类.当在有参构造函数后写上base时,只调用子类构造函数中有参的构造函数,隐藏父类无参构造函数. 二.代码案例 父类代码: #region 父类 /// <summary> /// 测试构造函数--需要被构造类 Fu /// </summary> class Fu { private int x;//一个简单的私有字段 /// <summary> /// 构造函数 ///

  • C#实现子类与父类的相互转换

    目录 子类与父类的相互转换 例一 例二 子类父类之间相互转换的问题 父类:动物类(Animal) 子类:狗类(Dog) 子类与父类的相互转换 1.父类不能直接强制转换成子类 2.子类可以强制转换成父类,但是在父类中只能取父类的字段与方法因此在一个父类对应多个子类的时候,不知道具体是哪个子类的时候,就可以先声明一个父类的类型.(如例1) 3.由1,2知,父类不能直接强制转换成子类,但是可以通过间接的方法进行转换,例1中有所体现:将子类转换成父类,然后再把父类转换成子类,如例2. 特别说明:虽然可以

  • python中子类调用父类函数的方法示例

    前言 本文主要给大家介绍了关于python子类调用父类函数的相关内容,Python中子类中的__init__()函数会覆盖父类的函数,一些情况往往需要在子类里调用父类函数.下面话不多说了,来一起看看详细的介绍: 如下例程里,???处是需要调用父类函数的地方,接下来结合例程具体介绍. # -*- coding:utf-8 -*- class Student: def __init__(self,name): self.name=name def ps(self): print('I am %s'%

  • PHP中子类重载父类的方法【parent::方法名】

    在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法重写. 子类中重载父类的方法就是在子类中覆盖从父类中继承过来的方法,父类中的方法被子类继承过来不就可以直接使用吗?为什么还要重载呢?因为有一些情况我们必须要覆盖的.例如,有一个"鸟"类,在这个类中定义了鸟的通用方法"飞翔".将"鸵鸟"类作为它的子类,

  • Python实现子类调用父类的方法

    本文实例讲述了Python实现子类调用父类的方法.分享给大家供大家参考.具体实现方法如下: python和其他面向对象语言类似,每个类可以拥有一个或者多个父类,它们从父类那里继承了属性和方法.如果一个方法在子类的实例中被调用,或者一个属性在子类的实例中被访问,但是该方法或属性在子类中并不存在,那么就会自动的去其父类中进行查找. 继承父类后,就能调用父类方法和访问父类属性,而要完成整个集成过程,子类是需要调用的构造函数的. 子类不显式调用父类的构造方法,而父类构造函数初始化了一些属性,就会出现问题

  • C++类继承之子类调用父类的构造函数的实例详解

    C++类继承之子类调用父类的构造函数的实例详解 父类HttpUtil: #pragma once #include <windows.h> #include <string> using namespace std; class HttpUtil { private: LPVOID hInternet; LPVOID hConnect; LPVOID hRequest; protected: wchar_t * mHostName; short mPort; string send

  • python中子类继承父类的__init__方法实例

    前言 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的 初始化 . 注意:这个名称的开始和结尾都是双下划线. 父类A class A(object): def __init__(self, name): self.name=name print "name:", self.name def getName(self): return 'A ' + sel

  • java子类继承父类实例-披萨的选择实现代码

    编写程序实现比萨制作.需求说明编写程序,接收用户输入的信息,选择需要制作的比萨.可供选择的比萨有:培根比萨和海鲜比萨. 实现思路及关键代码 1)分析培根比萨和海鲜比萨 2)定义比萨类 3)属性:名称.价格.大小 4)方法:展示 5)定义培根比萨和海鲜比萨继承自比萨类 6)定义比萨工厂类,根据输入信息产生具体的比萨对象 Pizza.java package zuoye; import java.util.Scanner; //父类 public class Pizza { String name;

  • Java编程关于子类重写父类方法问题的理解

    子类重新实现父类的方法称重写:重写时可以修改访问权限修饰符和返回值,方法名和参数类型及个数都不可以修改:仅当返回值为类类型时,重写的方法才可以修改返回值类型,且必须是父类方法返回值的子类:要么就不修改,与父类返回值类型相同.那么,该如何理解呢?为什么要是父类返回值类型的子类? 提出问题:子类必须重写父类所有方法吗? Java,子类不是必须重写父类所有方法的,分为以下两种情况: 父类方法为抽象方法时,子类必须重写(实现)所有父类的抽象方法: 父类方法为普通方法时,子类可以重写父类方法,也可以不重写

  • Java、C++中子类对父类函数覆盖的可访问性缩小的区别介绍

    前言 "Java 和 C++ 中子类对父类函数覆盖的可访问性缩小的问题"的题目看起来比较学术化,但的确是一个容易忽视的问题.本文力求详细阐述这一问题在 Java 以及 C++ 中的区别. 先介绍什么是"子类对父类函数覆盖的可访问性缩小".对于继承而言,子类可以覆盖父类的"虚函数"--尽管 Java 中没有虚函数这一术语,但可以把 Java 的所有函数都看作虚函数,因为 Java 的所有函数都可以被子类覆盖.这里仅借用"虚函数"

随机推荐