第5章-类

思考并回答以下问题:

  • 封装的目的是什么?

本章涵盖:

前言

第1章简单介绍了如何声明一个名为Hel1oMorld的新类。第2章介绍了C#内置的基元类型。由于已经学习了控制流以及如何声明方法,所以现在应学习如何定义自己的类型。这是任何C#程序的核心构造,正是由于C#支持类以及根据类来创建对象,所以我们说C#是一种面向对象语言。

本章利用C#介绍面向对象编程的基础知识。重点在于如何定义类,可以将类理解成对象的模板。

在面向对象编程中,之前学过的所有结构化(过程式)编程构造仍然适用。然而,将那些构造封装在类中,可以创建更大、更有条理以及更容易的维护程序。从结构化(过程式)的、基于控制流的程序转向面向对象的程序,是思维模式发生的一个根本性变化,因为面向对象编程提供了一个额外的组织层次。结果是较小的程序在某种程度上得到了简化。但更重要的是,现在更容易创建较大的程序,因为程序中的代码得到了更好的组织。

面向对象编程的关键优势之一是不需要完全从头创建新的程序。而是可以将现有的一系列对象组装到一起,并用新的功能扩展类,或者添加更多的类。

为了支持封装, C#必须支持类、属性、访问修饰符以及方法。本章着重讨论前3种构造,因为方法已在第4章进行了讨论。掌握这些基础知识之后,第6草将讨论如何通过面向对象编程实现继承和多态性。

面向对象编程

如今,成功编程的关键在于提供恰当的组织和结构,以满足大型应用程序的复杂需求。面向对象编程能够很好地解决问题。开发人员一旦熟悉了面向对象编程,除非写一些极为简单程序,否则很难回到结构化编程。

面向对象编程最基本的构造是类。一组类构成了编程抽象、模型或者模板,通常对应于一个现实世界的概念。例如, OpticalStorageMedia (光学存储媒体)类可能有一个Eject()方法,该方法会让光盘从播放器中弹出。OpticalstorageMedia类是现实世界的CD/DVD播放器对象的编程抽象。

类是面问对象编程的3个主要特征(封装、继承和多态性)的基础。

封装

封装的目的是隐藏细节。在必要的时候,细节仍然可以访问,但通过巧妙地封装细节,大的程序变得更容易理解,数据不会因为不慎而被修改,代码也变得更容易维护(因为对一处代码进行修改所造成的影响被限制在封装的范围之内)。方法就是封装的一个例子。虽然可以将代码从方法中拿出,把它们直接嵌入调用者的代码中,但将特定的代码重构成一个方法,能享受到封装所带来的好处。

继承

考虑这个例子: DVD是光学存储媒体的一个类型。它具有特定的存储容量,能容纳一部数字电影。CD也是光学存储媒体的一个类型,但它具有不同的特征。CD上的版权保护有别于DVD的版权保护,两者的存储容量也不同。无论CD还是DVD,它们都有别于硬盘、U盘和软盘。虽然所有这些都是“存储媒体”,但分别具有不同的特征--即使一些基本功能也是不同的,比如所支持的文件系统,以及媒体的实例是只读还是可读可写的。

面向对象编程中的继承允许在这些相似但又不同的物件之间建立“属于”(is a)关系。可以合理地认为DVD和CD都“属于”存储媒体。因而,它们都具有存储能力.类似地, CD和DVD都“属于”光学存储媒体,后者又“属于”存储媒体。

为上面提到的每种存储媒体类型都定义一个类,就得到一个类层次结构,它由一系列“属于”关系构成。例如,可将基类型(所有存储媒体都从它派生)定义成storageMedia(存储媒体)。CD, DVD、硬盘、U盘和软盘都属于StorageMedia。但是,CD和DVID不必直接从StorageMedia派生。相反,可以从中间类型OpticalStorageMedia (光学存储媒体)派生。可以用一幅UML ( Unified Modeling Language,统一建模语言)风格的类关系图

继承关系至少涉及两个类,其中一个是另一个的更具体的版本。在图5-1中HardDrive是更具体的storageMedia,虽然更特化的类型HardDrive属于StorageMedia,但反之不成立,因为storageMedia的一个实例并非肯定是HardDrive,如图5-1所示,继承涉及的类可能不止两个。

更具体的类型称为派生类型或者子类型。更常规的类型称为基类型或者超类型。也经常将基类型称为“父”类型,将派生类型称为它的“子”类型。虽然这种说法很常见,但可能会带来混淆。“子”毕竟不是一种“父” !本书将采用“派生类型”和“基类型”的说法。

为了从一个类型派生或继承,需要对那个类型进行特化,这意味着要对基类型进行自定义,为了满足特定的需要而调整它。基类型可能包含所有派生类型都适用的实现细节。继承最关键的一点是所有派生类型都继承了基类型的成员。派生类型中可以修改基类型的成员,但无论如何,派生类型除了自己显式添加的成员,还包含了基类型的成员。派生类型确保了用一致性的层次结构组织类。在这个层次结构中,派生类型比它们的基类型更特别。

多态性

多态性这个词由一个表示“多”的词和一个表示“态”的词构成。讲到对象时,多态性意味着一个方法或类型可以具有多种形式的实现。假定有一个媒体播放机,它既能播放音乐CD,也能播放包含MP3歌曲的DVD,然而, Play()方法的具体实现会随着媒体类型的变化而变化。在一个音乐CD对象上调用Play()方法,或者在一张音乐DVD上调用Play()方法,都能播放出音乐,因为每种类型都理解自己具体如何“播放”。媒体播放器唯一知道的就是公共基类型OpticalStorageMedia以及它定义了Play()方法的事实。在多态性的帮助下,不同的类型能自己照料一个方法的实现细节,因为共享同一个公共基类型(或接口)的多个派生类型也包含了相同的方法签名。

自己的总结

常量const和readonly的区别就是圆周率π和银行卡密码的区别。
你永远不能去修改π这个常量,只能把开始的时候把3.14赋值给它,无论什么时候都不能去修改它,也没有必要去修改它。
但是银行卡密码却是可以修改的。如果你愿意,你的家人也可以知道密码,但只有你可以修改密码,每次把卡激活的时候你都可以选择修改密码。
所以像一些科学知识,比如圆周率,重力等都可以用const。
不是这些可以用readonly。

属性的作用:
1、属性是对字段的封装,是为了安全性问题。
2、可以对字段进行额外的操作,通过setter进行逻辑处理。

简写形式
现在要写两块代码

所以需要简写代码,变成了一行。
当你开放Name为public时,定义的私有private string name已经没有意义,所以可以去掉,直接使用Name。name这个字段已经不存在了,方法里不能出现这个词。所以可以简写。

internal在项目中生效。
跨项目需要引用和引入命名空间

C#是关于类型的语言,int,list,class,delegate,struct,enum等都是类型。

栈和堆的区别

栈的空间比堆小,读写速度比堆快。

多态:是一种概念,比如一个方法返回多个对象,里氏替换原则

密封sealed就是为了让一个类可以从父类继承,但是不能作为其他类的父类。所以直接规定了密封关键字只可以用到override的方法上。

同时规定了粒度,用到类上是整个类不能被继承,用到方法上是粒度变小,方法不能被继承。

因为软件系统不是一个人开发的,我有权力让某个类或方法不能继承和重写。加上里氏替换原则,子类可以用作父类的实例,如果重写了,子类调用的就是自己的方法,父类的方法就作废了。用sealed可以避免这一情况。

抽象也和继承有关。抽象的必须继承。

继承衍生出了很多语法。

抽象、接口、虚方法、override、protected、sealed、里氏替换原则、base、单继承、多继承等都是继承相关的。如果面向对象除去继承,可以少掉非常多的语法。

继承完全可以单独作为一章,因为面向对象关于继承的太多了。

0%