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

 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. JZOJ 7392. 【2021.11.17NOIP提高组联考】数 (ds)

    \(\text{Problem}\) 元素带类型与权值,每次修改权值或类型,求区间每种类型和的 \(k\) 次方和 强制在线 \(\text{Solution}\) 显然简单分块,根据询问需要发现要 ...

  2. JZOJ 2020.07.30【NOIP提高组】模拟

    总结 本场比赛很不负责对待 暴力都没怎么打 一个半小时后才开始打题 很悲剧的只有 \(23+11+36=70\) 分 \(T1\) 4300. 装饰大楼 题目 略 思路 很无聊的找规律题 考场弃疗 \ ...

  3. JZOJ 4366. 【GDKOI2016】项链

    \(\text{Problem}\) 给出一个项链,删去连续的一部分,使剩下的对称,且长度最长 \(\text{Analysis}\) 可以发现,剩下的合法项链一定是由两个回文串接起来(由对称性质可知 ...

  4. TCTrack

    TCTrack TCTrack: Temporal Contexts for Aerial Tracking,空中追踪的时间上下文 论文 官方代码 贡献: 提出了一种时间自适应卷积TAdaCNN. 提 ...

  5. elasticsearch 内存分配设置

    一.背景 elasticsearch版本为2.3.3 elasticsearch 默认安装后设置的内存是1GB,对于现实业务来说太小 预计在五台机器上配置elasticsearch构建集群,但是构建索 ...

  6. mysql 服务安装与配置

    数据库服务下载与安装: 下载地址:MySQL Community Server 安装:跟随引导一路下一步,建议配置root密码,不然安装成功cmd验证却是要求密码.没有密码还需要执行命令重新设置密码, ...

  7. Installing Superset最新版本安装(笔记)

    官方文档:https://superset.apache.org/docs/installation/installing-superset-from-scratch 由于在centos上安装有各种问 ...

  8. go-fastdfs断点续传功能

    1)安装go-fastdfs: 可以从GitHub上获取go-fastdfs的源码,然后使用go get命令安装: go get github.com/sjqzhang/go-fastdfs 2)安装 ...

  9. 16.java八皇后问题

    问题描述:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即: 任意两个皇后都不能处于同一行 .同一列或同一斜线上,问有多少种摆法(92). 思路分析:1) 第一个皇后先放第一行第一列2) ...

  10. 12组-Beta冲刺-2/5

    一.基本情况 队名:字节不跳动 组长博客:https://www.cnblogs.com/147258369k/p/15594989.html Github链接:https://github.com/ ...