面向对象基础
2015-06-27 13:42
225 查看
对象组合 |
面向对象程序:正在运行的程序 = 对象 + 对象之间的合作关系
“对象组合”是对象合作关系的一种,其含义是“一个对象包容另一个对象”。
“一对一”对象组合的两种类型:
A对象完全包容B对象,容器对象管理被包容对象的生命期
B对象是独立的,A对象引用现成的B对象
一对多的对象组合方式
使用集合类型(如数组、List<T>之类)的内部字段,很容易实现一对多的对象组合方式。
对象组合示例
一对一:
类型一:WinForm应用中窗体与放在窗体上的控件(纯代码);
类型二:WPF和Android(使用XML声明+后台代码)
一对多
WinForm中的列表控件ListBox
对象组合的特殊形式——自引用类;
自己实例化自己:class MyClass{ MyClass obj; }
在没有指针的面向对象的编程语言中,自引用类可用于代替指针建立数据之间的关联。
如:使用自引用类实现链表:
对象复制 |
对象的“复制”,指的是吧一个现有的对象克隆一份,得到一个新的对象,这个新对象与老对象“一模一样”,但新、老对象是完全独立的!
对象的“浅复制”:将对象的每个字段都复制一遍
但,对于有引用对象的复合对象的复制却不能这么简单地复制
这是因为浅复制方式,无法复制出真正独立的新对象。
因此,需要进行“深复制”,在复制对象时,会把其包容的内部对象也复制一份,并且这个过程是“递归”进行的。
效果如下:
.NET基类库中定义了一个ICloneable接口,所有需要实现深复制的对象,都需要实现这个接口
对象序列化 |
“对象状态”,指某一时刻对象所拥有的各个字段值的集合。
对象状态是与时间关联的,在不同的时刻,对象可能处于不同的状态。
这里的“对象的状态”是一个宏观的概念,与特定类型的对象(如Thread)所定义的状态不是一回事。
对象的序列化:
将对象状态保存到另外一种媒介中,并在需要的时候可以从媒介中重新读取数据,重建对象的过程称为对象的“序列化”与“反序列化”。
在开发中,用于保存对象状态的常用媒介有:“流”和“字符串”。
流(Stream):一个抽象的概念,代表的是一连串有顺序的二进制数据。流中有一个读写指针,用于读取流中的数据。
使用流实现序列化:
.NET基类库中提供的几种流对象:
NetworkStream:底层使用套接字实现计算机间的数据传送;
FileStream:对文件的读取和修改;
PipeStream:进程间使用匿名管道进行数据交换;
MemoryStream:将内存中一个缓冲去作为存储媒介,向其写入和读取数据。
.NET的两种序列化方式(使用“格式化器(Formatter)”完成序列化工作)
二进制序列化:将对象的数据看成是二进制的数据而直接写入到流中。(BinaryFormatter)
XML序列化:将对象数据用XML方式表示之后再以纯文本的方式写入到流中。(SoapFormatter)
反序列化:
二进制反序列化采用 BinaryFormatter 对象的 DeSerialize() 方法完成,次方法返回一个Object类型的对象,同城还需要进行类型转换。
![](file:///C:/Users/Lin/AppData/Local/Temp/enhtmlclip/Image(185).png)
应用实例:大批量地复制对象
先对象序列化到内存流;
将流读写指针移回到开头,再反序列化,即可创建一个与原有对象“一模一样”的对象。
重复这个过程,就可以克隆多个对象。
对象比较 |
关键是指定出确定对象大小的比较规则!
C#中,实现了IComparable接口的对象可以相互比较大小,其实现方法CompareTo()方法用于定义对象的“比较规则”,其返回值表明了比较结果。
如果只需要比较两个对象是否相等,则可以重写Object类的Equals方法(建议做法是直接调用CompareTo方法)
重写Object.Equals方法的规则:
自反性(Reflexive):a.Equals(a)的值为真;
对称性(Sysmmetric):a.Equals(b) == b.Equals(a);
传递性(Transitive):若a.Equals(b)为真,b.Equals(c)真,则a.Equals(c)为真;
与null判等:a.Equals(null)的值为假。
若重写了Equals方法,则也需要重写GetHashCode方法(否则对象在需要使用Hash值的对象集合中时会出问题)
如果两个对象的比较结果相等,则每个对象的GetHashCode方法都必须返回相同值;
对象状态为改变时,对此调用它的GetHashCode方法,必须返回相同的值;
为了获得最佳性能,选择的哈希函数必须为所输入生成随机分布。
除了以上两种方法外,C#还可以重写“==”,但会增加代码的阅读难度。
示例:
ObjectCompare定义了一个Circle类,按照其“半径”大小确定大小关系,并使用重写对象的运算符的方法。
支持“大小”比较的对象,排序和查找都比较方便。
另外一种情况:类已经写好了,但又想实现比较、排序的功能,该如何实现呢?
这是可以定义第三方的类用于完成比较任务——对象比较器(Object Comparer)
编写对象比较器规则:只需要实现IComparer或IComparer<T>接口
小结:
当需要对象放到集合中能够实现排序和比较, 只需要对象实现IComparable接口同时重写Equals方法,这样就可以使用基类库中大量基于比较的算法代码;
当代码支持大小比较和判等是,将其放入一个标准集合中,就恩能直接支持排序和查找,使用起来更加方便;
如果对象不支持大小比较,可以使用外部对象比较器,其最大的好处是对同一个对象将其传个多个比较器可以实现以不同的方式比较对对象进行“动态”的排序和查找,使用起来更加灵活。另外一方面,可以将外部比较器简化为lamb代码,使代码更加紧凑。
对象的协作与信息交换 |
面向对象的程序运行时往往会创建多个对象,这些对象之间可能有着复杂的关系,相互协作,共同实现应用程序所提供个各项功能。
对象协作的本质就是对象间信息交换的问题,体现为对象之间的相互访问,即
相互存取字段/属性;
相互调用方法。
同一对象内部的信息交换;
类方法通过协作处理同一个类字段实现信息交换。
两个对象间的信息传送;
“主”→“从” 对象信息传送;
从窗体设置一个只写属性(供主窗体传入信息)和一个公有的接收信息的方法。
主窗体:在其创建从窗体对象并调用显示方法,通过从窗体对象的属性和其公有方法传送信息。
主窗体要有从窗体对象的引用,才可以访问从窗体的公有方法和属性。
“从→主”对象信息传送;
从窗体:设置供主窗体提取信息的公有属性、设置记录窗体关闭的“原因”(供主窗体查询)。
主窗体:创建从窗体对象,并依据从窗体提供的状态信息进行不同的处理方式。
“从→主”对象信息传送,让从窗体“主动”想主窗体“汇报工作”;
使用的编程技巧:
对象注入:主窗体使用this把自己的引用传送给从窗体;
“回调”:从窗体回调主窗体的公有方法。
回调:假设A new 了一个对象B,告诉它在XX条件下,就可以调用我的Y方法,之后A就不再关系这件事了。在遇到合适的条件后,B调用A所告诉它的方法。A创建的对象,其方法的调用不需要A处理,而是由其他人来调用。
从窗体:创建私有的主窗体的字段(值为null,用于保存主窗体对象的引用);在其构造函数中,其参数为主窗体对象(注入对象的引用);使用已经注入主窗体对象的引用的主窗体对象直接调用主窗体对象的方法。
主窗体:创建从窗体对象,同时向其传入this(引用自己(主窗体对象))完成构造方法;设置公有的方法。
给多个对象“广播信息”;
使用对象集合实现“消息广播”;
利用委托(方法引用列表的引用)实现“信息广播”;
一个委托变量包含一个方法引用列表,能“包含”多个方法,每个节点就是一个方法,调用一次委托变量,所有的方法都顺序执行。
利用事件实现“消息广播”(能用委托实现的功能都能用事件实现,并且操作也类似);
一个对象“监控”多个对象;
利用对象引用回调;
使用委托回调;
使用自定义事件;
使用全局静态字段和方法(构建了“全局”的字段和方法,多线程会出现性能损失,不推荐);
“多对多”的对象间信息交换;
可以使用“对象间相互执有对方的引用”的方式实现对象间的相互通讯,但当有“一堆”对象需要相互通讯时,就会使对象间奖励一个复杂的关联网络,耦合度极高。
如何解决:
改“多对多”为“一对多”;
相关文章推荐
- django admin 根据用户显示不同的列表以及编辑界面等
- Redis 笔记与总结5 Redis 常用命令之 键值命令 和 服务器命令 && 高级应用之 安全性 和 主从复制
- centos device eth0 does not seem to be present解决方法
- $GLOBALS['HTTP_RAW_POST_DATA'] 和$_POST的区别
- 设计模式——简单工厂模型
- sgu 246 分类: sgu 2015-06...
- sgu 246
- 【转】三种快速排序算法以及快速排序的优化
- sgu 246 分类: sgu 2015-06-27 13:40 20人阅读 评论(0) 收藏
- 模板方法
- 深入浅出NodeJS笔记(二)
- js encodeURI encodeURIComponent escape 方法的区别
- SQLite 解决:Could not load file or assembly 'System.Data.SQLite ... 试图加载格式不正确的程序(转)
- SQL Server MySQL 中的 in 与 null
- 升级SQL2005到2008过程中遇到的问题
- Maven —— 在MyEclipse中不能正常运行
- springmvc ajax请求处理跳转问题
- [.NET领域驱动设计实战系列]专题十一:.NET 领域驱动设计实战系列总结
- 医疗dcm格式图像解析成bmp格式图片
- mysql int(3)与int(11)的区别