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

 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. 脊柱关节病外周关节滑膜高表达的RANK/RANKL/OPG系统与炎症呈部分分离

    脊柱关节病外周关节滑膜高表达的RANK/RANKL/OPG系统与炎症呈部分分离Vandooren B, et al. Arthritis Rheum. 2008;58:718-729目的:脊 柱关节病 ...

  2. Ansible介绍以及基于角色搭建LNMP和zabbix

    1 ansible 常用指令总结,并附有相关示例. /usr/bin/ansible 主程序,临时命令执行工具 /usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man ...

  3. 通过源码分析RocketMQ主从复制原理

    作者:京东物流 宫丙来 一.主从复制概述 RocketMQ Broker的主从复制主要包括两部分内容:CommitLog的消息复制和Broker元数据的复制. CommitLog的消息复制是发生在消息 ...

  4. python中操控excel的几个库:xlwt,xlrd,xlutils

    一.xlrd和xlwt模块介绍 xlrd模块提供在任何平台上从excel电子表格(.xls和.xlsx)中提取数据的功能,xlwt模块提供生成与Microsoft Excel 95 到2003版本兼容 ...

  5. Linux操作命令(三)1.more命令 2.less命令 3.head命令 4.tail命令

    1.more 命令 分页显示文本文件的内容 more 命令,功能类似 cat ,cat 命令是将整个文件的内容从上到下显示在屏幕上. more 命令会一页一页的显示,方便使用者逐页阅读,而最基本的指令 ...

  6. 疑问:如何替代dtb文件

    学习设备树,想添加自己定义的节点,编译好了,但不知道如何替代原来的dtb文件

  7. autodesk2023全家桶 Autodesk 2023 所有产品下载地址

    autodesk2023全家桶 Autodesk 2023 所有产品下载地址 作者: 佚名 2022/4/10 11:51:24 Autodesk系列软件每年都会提前发布,目前autodesk2023 ...

  8. 2020icpc沈阳H

    优化转移DP Problem - H - Codeforces 题意 Aloha 要骑单车,可以单独花费 \(r\) 元骑 1 次,也可以购买某一种单车卡,第 \(i\) 种单车卡 \(c_i\) 元 ...

  9. Mybatis-Plus学习

    mybatis-plus 学习 系统环境 jdk8+mysql5.7+springBoot+mybatis最新版本+系统编码UTF-8 文件配置 application.properties # 应用 ...

  10. 只会Jquery,后端程序员如何学会前端(webpack,react,babel,es5,es6)

    写在前 希望通过短暂的学习,可以达到一下目标: 1.能看懂现在前端的工程化手段 2.知道当前前端群体中大致的解决问题的思路 3.当前的问题在哪里,技术发展趋势是什么 4.建立起自己的认知模型 文章内容 ...