《你必须知道的.NET》读书笔记一:小OO有大智慧
此篇已收录至《你必须知道的.Net》读书笔记目录贴,点击访问该目录可以获取更多内容。
一、对象
(1)出生:系统首先会在内存中分配一定的存储空间,然后初始化其附加成员,调用构造函数执行初始化,这样一个对象实体就完成了出生过程。
Person aPerson = new Person("小周" , 25);
(2)旅程:在某种程度上就是外界通过方法与对象交互,从而达到改变对象状态信息的过程。这也和人的生存之道暗合。
aPerson.ChangeName("Edison Chou");
(3)插曲:
3.1 继承之访问修饰符
-
- public:最高访问权限,公司的董事会具有最高的决策权与管理权;
- protected:部门经理,具有对本部门的直接管辖权,面向对象中体现为子类继承纵向关系的访问约定;
- internal:类似于公司的职能部门的职责,不管是否具有上下级关系,人力资源部都有管辖其他部门员工的能力;(面向对象中体现为同一程序集的访问权限,只要是隶属于同一程序集,对象即可访问其属性等,不管是否存在隶属关系;)
- protected internal:副总经理,从横向到纵向都有管理权;
- private:最低访问权,公司一般职员,管好自己即可;
3.2 多态实现方式-->在不同的情况下实现了不同的操作,而把决定权交给系统自行处理
-
- 接口实现多态
- 抽象类实现多态
(4)消亡:对象和人,有生必然也有死。
在.NET的世界中,对象的生命周期由GC来控制:GC管理所有的托管堆对象,当内存回收执行时,GC检查托管堆中不再被使用的对象,并执行内存回收操作;不被应用程序使用的对象,指的是对象没有任何引用。
二、继承
(1)继承的分类:实现继承与接口继承
(2)继承的本质:面向对象中类与类之间的一种关系;继承的类称为子类、派生类;而被继承类称为父类、基类或超类;通过继承,使得子类具有父类的属性和方法,同时子类也可以通过加入新的属性和方法或修改父类的属性和方法建立新的类层次;
(3)实现继承与接口继承的区别:
-
- 抽象类适合于有族层概念的类间关系,而接口最适合为不同的类提供通用功能
- 接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系
- 接口多定义对象的行为;抽象类多定义对象的属性
- 版本式的问题最好以抽象类来实现
- 因为值类型是密封的,所以只能实现接口,而不能继承类
(4)面向对象基本原则:多聚合,少继承;低耦合,高内聚;
Adapter模式实例-->类的Adapter模式与对象的Adapter模式相比,对象的Adapter模式通过聚合而非继承的方式来实现对原有系统的扩展,松散耦合,较少的新类型。
#region 类的Adapter模式 interface ITweetable { void ToTweet(); } public class ChickenAdapter : Chicken, ITweetable { public void ToTweet() { Console.WriteLine("Chicken crows."); } } #endregion #region 对象的Adapter模式 public class BirdAdapter : ITweetable { private Bird _bird; public BirdAdapter(Bird bird) { _bird = bird; } public void ShowType() { _bird.ShowType(); } public void ToTweet() { //为不同的子类实现不同的ToTweet行为 } } #endregion
三、封装
(1)封装的作用:
-
- 隐藏系统实现的细节,保证系统的安全性和可靠性;
- 提供稳定不变的对外接口,因此系统中相对稳定部分常被抽象为接口;
- 封装保证了代码模块化,提高了软件的复用和功能分离;
(2)结论:封装就是一个包装,将包装的内外分为两个空间,对内实现数据私有,对外实现方法调用,保证数据的完整性和安全性。
/// <summary> /// 用户类 /// </summary> public class Client { private string name; //用户姓名 public string Name { get { return name; } set { name = value == null ? String.Empty : value; } } //private string firstName; //private string secondName; //public string MyName //{ // get { return firstName + secondName; } //} private int age; //用户年龄 public int Age { get { return age; } set { if ((value > 0) && (value < 150)) { age = value; } else { throw new ArgumentOutOfRangeException("年龄信息不正确。"); } } } private string password; //用户密码 public string Password { get { return password; } set { if (value.Length < 6) password = value; } } //public string get_Password() //{ // return password; //} //public string set_Password(string value) //{ // if (value.Length < 6) // password = value; //} }
四、多态
(1)定义:可以呈现不同形式的能力或状态;
(2)分类:基类继承式多态与接口实现式多态;
(3)运行机制:动态绑定(在运行期通过检查虚拟方法表来确定动态关联覆写的方法)
(4)DEMO:多态版万能文件加载器(FileLoader)
interface IFileOpen { void Open(); } enum FileType { doc, pdf, txt, ppt, jpg, gif, mp3, avi } abstract class Files : IFileOpen { private FileType fileType = FileType.doc; public FileType FileType { get { return fileType; } } public abstract void Open(); } abstract class DocFile : Files { public int GetPageCount() { //To do code return 0; } } abstract class ImageFile : Files { public void ZoomIn() { //放大比例 } public void ZoomOut() { //缩小比例 } } abstract class MediaFile : Files { public void Play() { //播放媒体 } public void Pause() { //暂停播放 } public void Stop() { //停止播放 } } class WordFile : DocFile { public override void Open() { Console.WriteLine("Open the Word file."); } } class PdfFile : DocFile { public override void Open() { Console.WriteLine("Open the Pdf file."); } } class JpgFile : ImageFile { public override void Open() { Console.WriteLine("Open the Jpg file."); } } class AviFile : MediaFile { public override void Open() { Console.WriteLine("Open the Avi file."); } } class MpegFile : MediaFile { public override void Open() { Console.WriteLine("Open the Mpeg file."); } } class LoadManager { private IList<Files> files = new List<Files>(); public IList<Files> Files { get { return files; } } public void LoadFiles(Files file) { files.Add(file); } /// <summary> /// 打开所有文件 /// </summary> public void OpenAllFiles() { foreach(IFileOpen file in files) { file.Open(); } } /// <summary> /// 打开单个文件 /// </summary> /// <param name="file">文件接口对象</param> public void OpenFile(IFileOpen file) { file.Open(); } /// <summary> /// 获取文件类型 /// </summary> /// <param name="fileName">文件名</param> /// <returns>文件类型</returns> public FileType GetFileType(string fileName) { FileInfo fi = new FileInfo(fileName); return (FileType)Enum.Parse(typeof(FileType), fi.Extension); } } class FileClient { static void Main(string[] args) { //首先启动文件加载器 LoadManager lm = new LoadManager(); //陆续添加要处理的文件 lm.LoadFiles(new WordFile()); lm.LoadFiles(new PdfFile()); lm.LoadFiles(new JpgFile()); //打开文件 foreach (Files file in lm.Files) { //if(file is 爷爷选择的) //{ // file.Open(); //} file.Open(); } Console.ReadKey(); } }
五、接口
(1)本质:一种“契约”,用于规定一种规则由大家遵守;通过IL分析(借助于Reflector工具)可知,接口本质上仍然被标记为.class,一个不能被实例化的类。实现了接口的类方法在IL标记为override,表示覆写了接口方法实现。
public interface IDriveable { void Drive(); } public class BusDriver : IDriveable { public void Drive() { Console.WriteLine("有经验的司机可以驾驶公共汽车。"); } } public class CarDriver : IDriveable { public void Drive() { Console.WriteLine("小车司机开小汽车。"); } } public class TractorDriver : IDriveable { public void Drive() { Console.WriteLine("拖拉机司机驾驶拖拉机。"); } } public class AircraftDriver : IDriveable { public void Drive() { Console.WriteLine("飞行员可以驾驶飞机。"); } } public class DriverSchool { public static void Main_1_5_1()//Main_1_5_1 { IList<IDriveable> drivers = new List<IDriveable>(); drivers.Add(new BusDriver()); drivers.Add(new CarDriver()); drivers.Add(new TractorDriver()); foreach (IDriveable driver in drivers) { driver.Drive(); } } }
(2)规则:
-
- 接口隔离原则强调接口应该被实现为具有单一功能的小接口
- 接口支持多继承,既可以作用于值类型也可以作用于引用类型
- 接口不能被实例化,没有构造函数,接口成员被隐式声明为public
- 禁止为已发布的接口添加新的成员
本章思维导图