昨晚在处理父类与子类相互转换时,想把父类转换子类对象,发现编译不通过 ,类定义如下:

 public interface IPeople
{
int Age {
get;
set;
} string Name {
get;
set;
}
} public class People : IPeople
{
public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
} public class Student : People
{ }

测试代码:

 IPeople p = new People();
Student stu = (Student)p;

这里, People 继承 IPeople , Student 继承 People , 即 Student 是 People 子类 , 先创建父类对象,原后强转子类,运行报错:

如上,换个方式, Student , People 均继承 IPeople , 试试看:

 public class People : IPeople
{
public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
} public class Student : IPeople
{
public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}

一样报错:

这里 Student 与 People 均继承  IPeople , 仍报错 , Student 与 People 不能互相转换,但二者可以转成 IPeople ,做为通用方法传参使用。

如:

  static void Print(IPeople p) {
Console.WriteLine($"age:{p.Age}");
Console.WriteLine($"name:{p.Name}");
}

另一种合法转换,如子类转父类是充许的,在如上第一示例基础上,运行如下测试代码,一切正常:

  IPeople p = new Student();
Student stu = (Student)p;

这里可以推测 在内存中 创建(New Student())  对象,本质上就是 Student , 同理 创建 (New People()) 对象,本质上就是 People , 之所以子类能够转换父类,只是逻辑层转换(内存结构不变),因为子类继承父类所有功能属性。逻辑层面,子类转成父类后,能够像调用父类方法一样调用子类。

由于父类无法转换子类,因此只能自个写一些转换逻辑,比如 在子类构造中 传入父类对象,显示将父类属性copy 至子类,考虑到 copy 繁琐 , 可借助反射属性方式 自动同步。

  public class People : IPeople
{
public int Age {
get;
set;
}
public string Name {
get;
set;
}
} public class Student : People
{
public Student() { } public Student(People peo) {
SynchronizationProperties(peo, this);
} void SynchronizationProperties(object src , object des) {
Type srcType = src.GetType();
object val;
foreach (var item in srcType.GetProperties())
{
val = item.GetValue(src);
item.SetValue(des, val ); }
}
}

调用代码:

 //创建父类对象
People p = new People() { Age = 18, Name = "张三" }; //将父类对象传入子类,Copy 公共属性
Student stu = new Student(p); Console.WriteLine($"Name:{stu.Name} , Age:{stu.Age}");

输出结果:

C# 子类与父类互转注意项的更多相关文章

  1. 子类重载父类的方法“parent::方法名”转于 恩聪PHP学习教程

    在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法 ...

  2. python子类调用父类的方法

    python子类调用父类的方法 python和其他面向对象语言类似,每个类可以拥有一个或者多个父类,它们从父类那里继承了属性和方法.如果一个方法在子类的实例中被调用,或者一个属性在子类的实例中被访问, ...

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

    这篇文章主要介绍了C#中子类调用父类的实现方法,通过实例逐步分析了类中初始化构造函数的执行顺序问题,有助于加深对C#面向对象程序设计的理解,需要的朋友可以参考下     本文实例讲述了C#中实现子类调 ...

  4. java 子类重写父类的方法应注意的问题

    若想实现一个合格重写方法,而不是重载,那么必须同时满足下面的要求! A.重写规则之一:    重写方法不能比被重写方法限制有更严格的访问级别.(但是可以更广泛,比如父类方法是包访问权限,子类的重写方法 ...

  5. C#中通过类来继承两个接口,父类实例化接口中的方法,子类继承父类,调用方法

    实现了父类继承接口,父类实例化接口的方法,子类继承父类,子类调用父类的方法直接使用 代码如下: using System; using System.Collections.Generic; usin ...

  6. 子类重载父类的方法“parent:方法名”

    在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法 ...

  7. 转:C++:从子类访问父类的私有函数

    众所周知,c和c++的数组都是不安全的,因为无论c还是c++都不提供数组边界检查功能,这使得数组溢出成为可能.从某个意义上说,c和c++是一种缺少监督的语言,然而这也正是其魅力所在.c++给予程序员更 ...

  8. c++继承构造子类调用父类构造函数的问题及关于容器指针的问题及当容器里储存指针时,记得要手动释放

    看下面的一个问题: class Person { private: string name; public: Person(const string& s=""){ nam ...

  9. c++子类和父类成员函数重名

    子类和父类返回值参数相同,函数名相同,有virtual关键字,则由对象的类型决定调用哪个函数. 子类和父类只要函数名相同,没有virtual关键字,则子类的对象没有办法调用到父类的同名函数,父类的同名 ...

  10. PHP - 子类使用父类的构造函数

    /* * 子类使用父类中的构造方法. */ //父类方法 class Person { //父类中的构造方法 function __construct(){ echo '这是父类中的构造方法!'; } ...

随机推荐

  1. Ansible 多机自动化工具 初学笔记

    此文档仅张聪明同学个人笔记:新负责KTH-RPL Cluster GPU的漫漫学习长路 English Docs: https://docs.ansible.com/ansible/latest/in ...

  2. Postman操作指南

    基本使用 基本使用在这里不做记录,大多数人下载完就会用.这里记一下重点. 抓包浏览器 浏览器安装插件postman interceptor:插件在postman-interceptor界面最下面提示的 ...

  3. Linux CentOS 7 磁盘扩容(原有磁盘扩容,非新增磁盘)

    背景: 接上篇  https://www.cnblogs.com/si-yuan/p/17148835.html,只是展示出了磁盘大小,还需进行如下操作,去完成原有磁盘的扩容. ----------- ...

  4. 零基础解读ChatGPT:对人类未来工作是威胁还是帮助?

    摘要:火到现在的ChatGPT到底是什么?它背后有哪些技术?对于我们的工作和生活会有啥影响?快来一起了解吧~ 本文分享自华为云社区<零基础解读ChatGPT:对人类未来工作是威胁还是帮助?> ...

  5. 免杀之:C# XOR Shellcode

    免杀之:C# XOR Shellcode 目录 免杀之:C# XOR Shellcode 1 环境准备 2 制作Shellcode后门文件 2.1 编译环境准备 2.2 生成XORKryptor程序 ...

  6. 组织炎症水平高的RA患者接受TNF拮抗剂治疗的效果更好

    组织炎症水平高的RA患者接受TNF拮抗剂治疗的效果更好van der Pouw Kraan TC, et al. Ann Rheum Dis. 2008;67(4):563-6.目的:不同患者对TNF ...

  7. Vue学习笔记之表单绑定

    1. 概述 1.1. 什么是数据的双向绑定 Vue.js是一个MV VM框架, 即数据双向绑定, 即当数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化.这也算是Vu ...

  8. Unity的超大开放世界解决方案

    https://blog.csdn.net/u011105442/article/details/104614043

  9. CRM管理系统界面

  10. 安装torch_scatter,torch-sparse,torch-cluster,torch-spline-conv,torch-geometric

    1. 查询torch版本号 进入https://pytorch-geometric.com/whl/ 找到对应的torch版本>>点击进入 2. 找到匹配的包 点击下载即可 3. 使用pi ...