一、对象导论
1.1 抽象过程
面向对象的实质:程序通过添加新类型的对象使自身适用于某个特定问题。
五个基本特性:
**1、万物皆为对象:**对象除了存储数据之外,还可以在自身进行操作,理论上讲可以抽取待求解问题的任何概念化构件,将其表示为程序中的对象。
**2、程序是对象的集合,他们通过发送消息告诉彼此需要做的:**调用方法。
**3、每个对象都有自己的由其他对象所构成的存储:**对象可以包含对象,用现有对象创建新的对象。
**4、每个对象都拥有其类型:**对象是类的实例,类则是类型。区别对象的方式就是可以发送什么样的消息给它。
**5、某一特定类型的所有对象都可以接收同样的消息:**苹果可以接收的,水果也可以接收。
对象具有状态、行为和标识。
每个对象拥有属性、方法,在内存中拥有唯一的地址。
1.2 每个对象都有一个接口
每个对象都属于定义了特性和行为的某个特定的类。
因为类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型。
每个对象都有一个接口,接口确定了对某一对象所能发出的请求。
1.3 每个对象都提供服务
编写程序,你的目标就是去创建(或者是最好在现有代码库中寻找)能够提供理想的服务来解决问题的一系列对象
在良好的面向对象设计中,每个对象都可以很好地完成一项任务,但是它并不试图做更多的事情。
高内聚:指的是模块内部各个组件的关系。例如系统中存在A、B两个模块进行交互,如果修改了A模块,不影响B模块的工作,那么我们就认为A模块有足够的内聚
低耦合:指的是模块间的关系。A模块与B模块存在依赖关系,当A模块发生改变时,B模块仍然可以正常工作,那么就认为A与B是低耦合的。
1.4 被隐藏的具体实现
访问修饰符:private protected default public
**private:**对同一类内可见(不可以修饰外部类)
**protected:**对同一包内的类和所有字类可见
**default:**在同一包内可见
**public:**所有类可见
增加程序安全性,使其他程序员只可以调用你的想让他调用的方法,具体实现隐藏起来,增加安全性
1.5 复用具体实现
在类中加入原有类(对象)进行复用。
因为是使用现有的类合成新的类,所以这种概念被称为组合,如果组合是动态发生的,那么它通常被称为聚合。
组合通常被称为has-a(拥有)的关系。(汽车拥有引擎)
1.6 继承
以现有的类为基础,复制它,然后通过添加和修改这个副本来创建新类叫做继承。
当源类(基类、超类或父类)发生变动时,被修改的副本(导出类、继承类或子类)也会反映出这些变动。
两个类型可以有相同的特性和行为,但是其中一个类型可能比另一个含有更多的特性,并且可以处理更多的消息(或者以不同的方式来处理消息)
所有可以发送给基类对象的消息同时也可以发送给导出类对象,由于通过发送给类的消息的类型可知类的类型,所以这也就意味着导出类与基类具有相同的类型。
有两种方法可以使基类与导出类产生差异
1、直接在导出类中添加新的方法
2、改变现有基类的方法的行为。这被称之为覆盖(重写)。
扩展:
1、不继承构造方法,但是会在子类的构造方法调用父类构造方法,帮助子类进行初始化工作。
2、不继承私有属性和方法,拥有但是不可以调用,因为创建子类首先调用父类的构造方法,所以字类拥有弗雷德私有属性和方法,但是不可以使用,如果父类提供相应访问方法(get、set)是可以调用的。
3、不继承static属性和方法,static属于类本身,不可重写,不具有多态性。
1.6.1 “是一个” 与 “像是一个”关系
“是一个” 与 “像是一个”主要区别在于是否在子类中添加新的方法
**“是一个”:**不添加新的接口元素,只在原有的基础上进行改变,意味着导出类与基类是完全相同的类型,因为具有完全相同的接口,结果可以用导出类对象来完全替代一个基类对象。这种替代称为“纯粹替代”,通常称之为替代原则。
**“像是一个”:**添加新的接口元素,这个新类型仍然可以替代基类,但是这种替代并不完美,因为基类无法访问新添加的方法。
1.7 伴随多态的可互换对象
非面向对象编程采用前期绑定,前期绑定的意思是编译器产生对一个具体函数名字的调用,运行时将这个屌用解析到将要被执行的代码的绝对地址。
在OOP中程序直到运行时才能够确定代码的地址,面向对象程序设计语言使用了后期绑定的概念,当向对象发送消息时,被屌用的代码直到运行时才能确定。
把导出类看做是她它的基类的过程称为向上转型。
多态的理解有待增强
1.8 单根继承结构
Java中只有单继承,java所有类都继承Object的这个基类。
单继承结构保证所有对象都具备某些功能。所有对象都可以很容易的在堆上创建,而参数传递也得到了极大的简化。
单继承结构使垃圾回收器的实现变得容易的多,由于所有对象都保证具有其类型的信息,因此不会因无法确定对象的类型而陷入僵局。
1.9 容器
用来存储对象,我们不知道解决问题的时候具体需要多少个对象,与他们需要存活多久,所以创建另一种对象类型,这种新的对象类型持有对其他对象的引用。
java内有很多种类型的容器,设计这些不同容器主要有两点原因:
1、不同容器提供了不同类型的接口和外部行为。(他们之中的某种容器提供的解决方案可能比其他容器灵活的多)
2、不同容器对于某些操作具有不同的效率。(ArrayList 查询快 在中间插入慢,因为涉及到移动下标操作,LinkedList 查询慢 在中间插入快,链表结构只需在元素前后加上地址即可)
1.9.1 参数化类型
在Java SE5出现之前,容器保存的都是Object类型,存放的时候容易(向上转型),取的时候危险(向下转型),因为取出的结果是Object类型的。
Java SE5 推出了范型(参数化类型)的概念,每个集合只可以存放指定类型的对象。
1.10 对象的创建和生命周期
Java中创建对象只需要使用new关键字,就可以在堆上面创建一个对象,并且Java有垃圾回收器机制,这个机制会自动发现对象何时不再被使用,并继而销毁它。
1.11 异常处理:处理错误
Java内置异常处理,而且强制你必须使用它,它是唯一可接受的错误报告方式,如果没有正确的处理异常的代码,那么就会得到一条编译时的出错消息。
异常处理不是面向对象的特征,异常处理在面向对象语言出现之前就已经存在了。
1.12 并发编程
在同一时刻,处理多个任务的思想叫做并发,程序中彼此独立运行的部分称之为线程。
通常,线程只是一种为单一处理器分配执行时间的手段。但是如果操作系统支持多处理器,那么每个任务都可以被指派给不同处理器,并且他们是在真正的并行执行。
并发看起来简单,但是有一个隐患:共享资源,可以通过锁去解决,具体详见后续内容。