.NET----- 工作多年心得,补充基础必备

第一题 —有关继承的概念
密封类不可以被继承。
继承关系中,我们更多的是关注其共性而不是特性,因为共性是层次复用的基础,而特性是系统扩展的基点。
实现单继承,接口多继承。
从宏观来看,继承多关注于共通性;而多态多着眼于差异性。
继承的层次应该有所控制,否则类型之间的关系维护会消耗更多的精力。
面向对象原则:多组合,少继承;低耦合,高内聚。

.NET 中对象的继承两个原则:
1.关注对象原则:调用子类还是父类的方法,取决于创建的对象是子类对象还是父类对象,而不是它的引用类型。例如 Bird bird2 = new Chicken()时,我们关注的是其创建对象为 Chicken 类型,因此子类将继承父类的字段和方法,或者覆写父类的虚方法,而不用关注 bird2 的引用类型是否为Bird。引用类型不同的区别决定了不同的对象在方法表中不同的访问权限。
根据关注对象原则,那么下面的两种情况又该如何区别呢?
Bird bird2 = new Chicken();
Chicken chicken = new Chicken();
根据我们上文的分析,bird2 对象和 chicken 对象在内存布局上是一样的,差别就在于其引用指针的类型不同:bird2 为 Bird 类型指针,而 chicken 为 Chicken 类型指针。以方法调用为例,不同的类型指针在虚拟方法表中有不同的附加信息作为标志来区别其访问的地址区域,称为 offset。不同类型的指针只能在其特定地址区域内进行执行,子类覆盖父类时会保证其访问地址区域的一致性,从而解决了不同的类型访问具有不同的访问权限问题。

  1. 执行就近原则:对于同名字段或者方法,编译器是按照其顺序查找来引用的,也就是首先访问离它创建最近的字段或者方法,例如上例中的 bird2,是 Bird 类型,因此会首先访问 Bird_type(注意编译器是不会重新命名的,在此是为区分起见),

封装的概念
在面向对象三要素中,封装特性为程序设计提供了系统与系统、模块与模块、类与类之间交互的实现手段。
封装隐藏了类内部的具体实现细节,对外则提供统一访问接口,来操作内部数据成员。这样实现的好处是实现了 UI 分离,程序员不需要知道类内部的具体实现,只需按照接口协议进行控制即可。同时对类内部来说,封装保证了类内部成员的安全性和可靠性。

字段,属性,方法
通常系统需求描述的核心名词,可以抽象为类,而对这些名词驱动的动作,可以对应地抽象为方法。当然,具体的设计思路要根据具体的需求情况,在整体架构目标的基础上进行有效的筛选、剥离和抽象。取舍之间,彰显 OO 智慧与设计模式的魅力。

字段(field)
通常定义为 private,表示类的状态信息。
封装的第一个原则就是:将字段定义为 private。
封装原则告诉我们:类的字段信息最好以私有方式提供给类的外部,而不是以公有方式来实现,否则不适当的操作将造成不必要的错误方式,破坏对象的状态信息,数据安全性和可靠性无法保证。

属性(property)
通常定义为 public,表示类的对外成员。
字段设置为了private,则需要通过属性对外进行暴露。
编译器的执行逻辑是:如果发现一个属性,并且查看该属性中实现了 get 还是 set,就对应地生成 get_属性名、set_属性名两个方法。因此,我们可以说,属性的实质其实就是在编译时分别将 get 和 set 访问器实现为对外方法,从而达到控制属性的目的,而对属性的读写行为伴随的实际是一个相应方法的调用,它以一种简单的形式实现了方法。
通过对公共属性的访问来实现对类状态信息的读写控制,主要有两点好处:一是避免了对数据安全的访问限制,包含内部数据的可靠性;二是避免了类扩展或者修改带来的变量连锁反应。
还有一种含参属性,在 C#中称为索引器(indexer),对 CLR 来说并没有含不含参数的区别,它只是负责将相应的访问器实现为对应的方法,不同的是含参属性中加入了对参数的处理过程罢了。

方法(method)
封装了类的行为,提供了类的对外表现。用于将封装的内部细节以公有方法提供对外接口,从而实现与外部的交互与响应。
从上面属性的分析我们可知,实际上对属性的读写就是通过方法来实现的。因此,对外交互的方法,通常实现为 public。

多态的概念
分类:根据其实现的方式我们可以进一步分为基类继承式多态和接口实现式多态。
运行机制:从技术实现角度来看,是.NET 的动态绑定机制成就了面向对象的多态特性。
动态绑定,又叫晚期绑定,是区别与静态绑定而言的。静态绑定在编译期就可以确定关联,一般是以方法重载来实现的;而动态绑定则在运行期通过检查虚拟方法表来确定动态关联覆写的方法,一般以继承和虚方法来实现。严格来讲,.NET 中并不存在静态绑定。所有的.NET 源文件都首先被编译为 IL 代码和元数据,在方法执行时,IL 代码才被 JIT 编译器即时转换为本地 CPU 指令。JIT 编译发生于运行时,因此也就不存在完全在编译期建立的关联关系,静态绑定的概念也就无从谈起。
意义:多态提供了对同一类对象的差异化处理方式,实现了对变化和共性的有效封装和继承,体现了“一个接口,多种方法”的思想,使方法抽象机制成为可能。在.NET 中,默认情况下方法是非虚的,以 C#为例必须显式地通过 virtual 或者 abstract 标记为虚方法或者抽象方法,以便在子类中覆写父类方法。在面向对象的基本要素中,多态和继承、多态和重载存在紧密的联系,正如前文所述多态的基础就是建立有效的继承体系,因此继承和重载是多态的实现基础

第二题: class和struct的区别
1.class 是引用类型,继承自 System.Object 类;struct 是值类型,继承自 System.ValueType类,因此不具多态性。但是注意,System.ValueType 是个引用类型。
2.从职能观点来看,class 表现为行为;而 struct 常用于存储数据。
3.class 支持继承,可以继承自类和接口;而 struct 没有继承性,struct 不能从 class 继承,也不能作为 class 的基类,但 struct 支持接口继承
4.class 可以声明无参构造函数,可以声明析构函数;而 struct 只能声明带参数构造函数,且不能声明析构函数。因此,struct 没有自定义的默认无参构造函数,默认无参构造器只是简单地把所有值初始化为它们的 0 等价值
5.实例化时,class 要使用 new 关键字;而 struct 可以不使用 new 关键字,如果不以 new 来实例化 struct,则其所有的字段将处于未分配状态,直到所有字段完成初始化,否则引用未赋值的字段会导致编译错误。
6.class 可以实抽象类(abstract),可以声明抽象函数;而 struct 为抽象,也不能声明抽象函数。
7.class 可以声明 protected 成员、virtual 成员、sealed 成员和 override 成员;而 struct 不可以,但是值得注意的是,struct 可以重载 System.Object 的 3 个虚方法,Equals()、ToString()和GetHashTable()。
8.class 的对象复制分为浅拷贝和深拷贝(该主题我们在本系列以后的主题中将重点讲述,本文不作详述),必须经过特别的方法来完成复制;而 struct 创建的对象复制简单,可以直接以等号连接即可。
9.class 实例由垃圾回收机制来保证内存的回收处理;而 struct 变量使用完后立即自动解除内存分配。
10.作为参数传递时,class 变量是以按址方式传递;而 struct 变量是以按值方式传递的。

第三题: 接口和抽象类的区别
1接口支持多继承;抽象类不能实现多继承。
2接口只能定义抽象规则;抽象类既可以定义规则,还可能提供已实现的成员。
3接口是一组行为规范;抽象类是一个不完全的类,着重族的概念。
4接口可以用于支持回调;抽象类不能实现回调,因为继承不支持。
5接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法;抽象类可以定义字段、属性、包含有实现的方法。
6接口可以作用于值类型和引用类型;抽象类只能作用于引用类型。例如,Struct 就可以继承接口,而不能继承类。

接口和抽象类适用的场合:
1抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
2接口着重于 CAN-DO 关系类型,而抽象类则偏重于 IS-A 式的关系;
3接口多定义对象的行为;抽象类多定义对象的属性;
4接口定义可以使用 public、protected、internal 和 private 修饰符,但是几乎所有的接口都定义为 public,原因就不必多说了。
5接口不变 ,是应该考虑的重要因素。所以,在由接口增加扩展时,应该增加新的接口,而不能更改现有接口。
6尽量将接口设计成功能单一的功能块,以.NET Framework 为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable 等都只包含一个公共方法。
7接口名称前面的大写字母 I 是一个约定,正如字段名以下划线开头一样,请坚持这些原则。
8在接口中,所有的方法都默认为 public。
9如果预计会出现版本问题,可以创建 抽象类 。例如,创建了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)来应对以后可能出现风马牛的事情。而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。
10从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
11对抽象类不能使用 new 关键字,也不能被密封,原因是抽象类不能被实例化。
12在抽象方法声明中不能使用 static 或 virtual 修饰符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值