目录:

【C#小知识】C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用

【C#小知识】C#中一些易混淆概念总结(二)--------构造函数,this关键字,部分类,枚举

【C#小知识】C#中一些易混淆概念总结(三)--------结构,GC回收,静态成员,静态类

【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine()

----------------------------------------------分割线--------------------------------------------------

这一系列的文章在园子里还是比较受欢迎的。有一些留言指出了其中理论性的错误,还有问自己是否毕业,怎么写出来这些文章的,有没有培训过等等问题。

下面就一并的回答这些问题吧。

1)自己今年六月份毕业,现在在帝都实习。不过在学校已经做过一些C#开发了,现在也是做.NET开发工作。

2)文章中很多知识是自己以前在网上下载的视频教程,学习过程中所记的笔记。也就是在年前的时候,突然有一天发现自己的笔记本记了差不多块一本了,之前也没时间整理过,所以就想着把它们整理成博客文章,顺便温习一下这些笔记知识。

3)有园友问自己是不是在传智培训过。首先说我没有培训过,但是非常感谢传智公开的一些自学教程。因为自己也是这些视频的受益者,学到了很多知识,养成了一些好的学习习惯。

4)在整理笔记的过程中遇到了很多问题,其中自己参考了《C#本质论》,《CLR via C#》还有就是MSDN的官方文档。

3)不管怎样还是会遇到一些自己解决不掉或者弄不清楚的问题,这个过程使用了Google搜索并和请教了一些园友。

4)错误总是会存在。谢谢看我博客的读者你们的细心,指出了我博文中的错误。确定这些错误后,我都立即修改了自己的文章。

---------------------------------------------分割线-----------------------------------------------------

今天开始上班了。这几天研究学习了一下思维导图,感觉用它整理自己的知识非常的方便。所以,以后写博客完成一个知识点,都会用思维导图做一个总结。也能让大家对所要读的内容有一个整体的把握。

我用的思维导图软件是FreeMind(免费的,但是得装JDK),因为刚开始学习使用,很多操作技巧不是很熟练,做出来的导图估计也不是很好,希望大家见谅。

首先,里氏替换原则。

这是理解多态所必须掌握的内容。对于里氏替换原则维基百科给出的定义如下:

为什么子类可以替换父类的位置,而程序的功能不受影响呢?

当满足继承的时候,父类肯定存在非私有成员,子类肯定是得到了父类的这些非私有成员假设,父类的的成员全部是私有的,那么子类没办法从父类继承任何成员,也就不存在继承的概念了)。既然子类继承了父类的这些非私有成员,那么父类对象也就可以在子类对象中调用这些非私有成员。所以,子类对象可以替换父类对象的位置。

来看下面的一段代码:

 class Program
{
static void Main(string[] args)
{
Person p = new Person(); Person p1 = new Student(); Console.ReadKey();
}
} class Person
{
    //父类的私有成员
    private int nAge; public Person()
{
Console.WriteLine("我是Person构造函数,我是一个人!");
} public void Say()
{
Console.WriteLine("我是一个人!");
} } class Student : Person
{
public Student()
{
Console.WriteLine("我是Student构造函数,我是一个学生!");
} public void SayStude()
{
Console.WriteLine("我是一个学生!");
}
} class SeniorStudent : Student
{
public SeniorStudent()
{
Console.WriteLine("我是SeniorStudent构造函数,我是一个高中生!");
}
public void SaySenior()
{
Console.WriteLine("我是一个高中生!");
}
}

我们运行打印出的结果是:

根据前面的构造函数的知识很容易解释这个结果。那么我们在Main()函数中添加如下的代码:

static void Main(string[] args)
{
Person p = new Person();
p.Say();
  
Person p1 = new Student();
p1.Say();
Console.ReadKey();
}

在访问的过程中,可以发现p只可以访问父类的say

而p1也只可以访问父类的Say方法

其实在上面的代码中,就满足了里氏替换原则。子类的Student对象,替换了父类Person对象的位置。

那么它们在内存中发生了些什么呢?如下图:

由上可以知道,当一个父类的变量指向一个子类对象的时候只能通过这个父类变量调用父类成员,子类独有的成员无法调用。

同理我们可以推理出,子类的变量是不可以指向一个父类的对像的

但是当父类变量指向一个子类变量的时候,可以不可以把父类的变量转化成子类的对象呢?看下图

关于引用类型的两种转换方式:

由上面的代码我们已经知道了一种转换,就是在变量钱直接加需要转换的类型,如下代码:

Student s2 = (Student)p1;

那么第二种转换方式就是使用as关键字,如下代码:

 //将指向子类对象的变量转化成子类类型
Student s2 = (Student)p1; //使用as关键字,转换失败返回一个null值
Student s3 = p1 as Student;

使用as关键字和第一种强制转换的区别就是,第一种如果转换失败会抛异常,第二种转换失败则返回一个null值。

思维导图总结如下:

 二,虚方法

使用virtual关键字修饰的方法,叫做虚方法(一般都是在父类中)。

看下面的一段代码:

class Person
{
private int nAge;
public Person()
{
Console.WriteLine("我是Person构造函数,我是一个人!");
} //这里定义了一个虚方法
public virtual void Say()
{
Console.WriteLine("我是一个人!");
} } class Student : Person
{
//子类使用override关键字改写了父类的虚方法
public override void Say()
{
Console.WriteLine("我是一个学生!");
}
public Student()
{
Console.WriteLine("我是Student构造函数,我是一个学生!");
} public void SayStude()
{
Console.WriteLine("我是一个学生!");
}
}

紧接着在main()函数中添加如下的代码:

static void Main(string[] args)
{
Person p = new Person();
p.Say(); Person p1 = new Student();
p1.Say(); Student s = new Student();
s.Say();
Console.ReadKey();
}

打印结果如下:

我们很明显的可以发现,第二个表达式满足里氏替换原则,p1.Say()执行的应该是父类的Say()方法,但是这里却执行了子类的Say()方法。

这就是子类使用override关键字的Say()方法覆盖了父类的用Virtual关键字修饰的Say()方法。

我们使用动态图片看一下调试过程,

①首先是没有使用任何关键字:

由上可以看出直接跳入父类,执行了父类的Say()方法;

②再看使用virtual和override关键字的动态调试图片,如下

可以看到直接到子类去执行override关键字修饰的Say()方法。

那么如果父类使用virtual关键字修饰,而子类没有重写该方法时会怎么样呢?如下面的代码:

class Program
{
static void Main(string[] args)
{ Person p1 = new Student();
p1.Say();
Console.ReadKey();
}
} class Person
{
private int nAge;
public Person()
{
Console.WriteLine("我是Person构造函数,我是一个人!");
} //这里定义了一个虚方法
public virtual void Say()
{
Console.WriteLine("我是一个人!");
} } class Student : Person
{
//子类中没有出现override关键字修饰的方法 public void SayStude()
{
Console.WriteLine("我是一个学生!");
}
}

执行结果如下:

所以,如果子类找不到override方法,则会回溯到该子类的父类去找是否有override方法,知道回溯到自身的虚方法,并执行。

虚方法知识总结的思维导图如下:


毕业实习交流群:221376964。你也可以关注我的新浪微博进行交流。

版权声明:本文为博主原创文章,未经博主允许不得转载。

【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏的更多相关文章

  1. 【C#小知识】C#中一些易混淆概念总结(二)--------构造函数,this关键字,部分类,枚举 分类: C# 2014-02-03 01:24 1576人阅读 评论(0) 收藏

    目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 继上篇对一些C#概念问题进行细节的剖析以后,收获颇多.以前,读书的时候,一句话一掠而 ...

  2. iOS中UITextField 使用全面解析 分类: ios技术 2015-04-10 14:37 153人阅读 评论(0) 收藏

    //初始化textfield并设置位置及大小   UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...

  3. 解决ORA-29857:表空间中存在域索引和/或次级对象 & ORA-01940:无法删除当前连接的用户问题 分类: oracle sde 2015-07-30 20:13 8人阅读 评论(0) 收藏

    今天ArcGIS的SDE发生了一点小故障,导致系统表丢失,所以需要重建一下SDE数据库,在删除SDE用户和所在的表空间过程中遇到下面两个ORA错误,解决方法如下: 1)删除表空间时报错:ORA-298 ...

  4. VS2010中使用命令行参数 分类: c/c++ 2014-07-11 22:24 634人阅读 评论(0) 收藏

    在Linux下编程习惯了使用命令行参数,故使用VS2010时也尝试了一下. 新建项目,c++编写程序如下: #include<iostream> #include<fstream&g ...

  5. C/C++中const的用法 分类: C/C++ 2015-07-05 00:43 85人阅读 评论(0) 收藏

    const是C语言的关键字,经C++进行扩充,变得功能强大,用法复杂.const用于定义一个常变量(只读变量),当const与指针,引用,函数等结合起来使用时,情况会变得复杂的多.下面将从五个方面总结 ...

  6. 认识C++中的临时对象temporary object 分类: C/C++ 2015-05-11 23:20 137人阅读 评论(0) 收藏

    C++中临时对象又称无名对象.临时对象主要出现在如下场景. 1.建立一个没有命名的非堆(non-heap)对象,也就是无名对象时,会产生临时对象. Integer inte= Integer(5); ...

  7. Java获取项目中的路径 分类: Java Game 2014-08-14 10:17 122人阅读 评论(0) 收藏

    在项目中经常需要获取某个文件的路径: 在这里提供一些获取路径的方法.. 1.此种方式获取的路径,是当前类所在的路径: UserDAOTest.class.getResource("UserD ...

  8. 如何在hadoop中控制map的个数 分类: A1_HADOOP 2015-03-13 20:53 86人阅读 评论(0) 收藏

    hadooop提供了一个设置map个数的参数mapred.map.tasks,我们可以通过这个参数来控制map的个数.但是通过这种方式设置map的个数,并不是每次都有效的.原因是mapred.map. ...

  9. JAVA swing中JPanel如何实现分组框的效果以及设置边框颜色 分类: Java Game 2014-08-16 12:21 198人阅读 评论(0) 收藏

    代码如下: import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; import javax.sw ...

随机推荐

  1. 记一次web服务模块开发过程

    一.前言 之前在分析WCS系统的过程中,也赶上要开发其中的一个模块,用于和AGV系统对接完成一些取货.配盘等任务:在这里将这次模块开发的全过程记录一下,以便自己以后开发时能够更加快速的明白流程. 二. ...

  2. ansible-playbook 主机变量2

    ansible-playbook 配置 hosts 后可以指定变量,通过-k 可以交互输入密码,也可以将密码写在 hosts 文件中. 入口 yaml 文件中通过 {{ ** }} 获取变量,命令行通 ...

  3. MFC 的SetWindowPos 用法

    转自于:http://hi.baidu.com/max_new/blog/item/e2bbe607b1f127c57b8947c0.html 许多软件,特别是占桌面面积不是很大的软件,通常都提供了一 ...

  4. JSTL自定义函数完成ACL即时认证

    即时认证是指,用户进行查询或更新操作时,判断该用户进行是否对该操作有权限. 这里以判断用户是否有删除权限为例.如果用户有删除权限,即显示该按钮:如果没有删除权限,则不显示该按钮. 1.Manager层 ...

  5. http://www.cnblogs.com/xalion/p/5111279.html

    https://quality.embarcadero.com/secure/Dashboard.jspa 注册成 delphi qc

  6. IIS发布网站之后,页面图片和js未加载出错

    [IIS相关]mvc做的web发布之后,运行之后界面上的图片和js都没有加载出来.      解决方案:安装IIS的时候需要勾选ASP选项,否则会出现这种情况. 如果项目是用.Netframework ...

  7. Algebraic Kernel ( Arithmetic and Algebra) CGAL 4.13 -User Manual

    1 Introduction Real solving of polynomials is a fundamental problem with a wide application range. T ...

  8. 博客迁址 xpeng.scorpionstudio.com

    这里不再更新!现在博客的正式地址是: http://xpeng.scorpionstudio.com

  9. CentOS 6 - 升级内核

    有的时候,需要升级Linux内核,今天我就是在CentOS 6中升级内核,在没有升级内核之前,我的CentOS 6只有2.6.32这一个内核,也是默认启动的内核.下面就开始一步步操作升级内核了! 一, ...

  10. 【文文殿下】【CF724C】Ray Tracing (中国剩余定理)

    题解 我们考虑将棋盘扩大一倍,这样相当于取膜.然后,我们只要对x,y,的位置分类讨论,做四次crt就行.具体细节看文文代码. #include<cstdio> #include<al ...