万物皆对象

一、抽象过程:


1,万物皆为对象。

狗、房子这种具体的事物是对象,“服务”这种抽象的概念也是对象。

你可以用对象来存储东西。狗对象可以存储狗头,狗腿等。“服务”对象可以存储服务类型、服务员、顾客等。

你可以要求对象执行某种操作。比如,让狗叫一声,让“服务”对象做一个“送货上门”的动作。

2,程序是对象的集合

程序中的各个对象通过发送消息来告诉彼此要做什么,来合作完成一项任务。比如你调用某个对象的某个方法,“调用”的过程就是“发消息”。

3,一个对象可以由许多其他对象组成。

4,每一个对象都有自己的类型。

比如,A a=new A();那么,a的类型就是A,“类”就是“类型”。你创建了一个狗对象,那么,狗对象的类型就是狗。

类与类区分开来的一个重要因素是:“可以发送什么样的消息给它”,即:每个类都有自己的方法。

5,某一特定类型的对象可以接收同样的消息。

接收消息即调用方法。泰迪类、博美类都属于狗类。上面这句话的意思就是:因为泰迪和博美都是狗,所以,它们都能够调用狗的“叫”、“跑”等方法。比如:

BoMei和TaiDi继承了Dog,所以,它们创建的对象可以调用Dog的方法。

这就意味着,我们要编写BoMei或者TaiDi相关的代码时,只需要编写Dog相关代码就可以,这就是OOP(面向对象设计)中最强有力的概念之一。如下:

我给Dog定义了legs属性。在test(Dog dog)方法中,我传入的参数是“Dog”,操作的也是Dog类的属性。但是当我在16行调用这个方法时,我传的参数是“BoMei”对象,此时,操作的就是BoMei。

同理,当我们要操作的是TaiDi对象时,给test传入TaiDi对象就行。我们就不必分别为TaiDi和BoMei再定义一个test(TaiDi ta)、test(BoMei bo)方法。

6,每个对象都是唯一的

对象都有状态、行为、标识、类型。比如上面的BoMei类,“状态”就是“变量”,就是“属性”,上面的BoMei类,legs就是它的“状态”。行为就是“方法”、“函数”,对应上面的bark()、eat()等。行为可以改变状态,比如上面的test(Dog dog)改变了legs属性的值。类型就是对象所属的类,而“标识”就相当于身份证一样,这在java中表现为:每个对象在内存中都有唯一的地址。

二、每个对象都有一个接口

苹果有皮、有核,是甜的,长在树上。梨也有皮,也有核,也是甜的,也长在树上。那么苹果和梨有很多相似性,被划分到同一类型:水果类。这个“水果类”就是一个抽象数据类型(所谓的抽象,就是抽取了一些类似的表象东西,比如皮、核、味道、生长环境等)。

抽象数据类型的运作方式与基本数据类型是一致的。比如对于基本数据类型,可以这样使用:

对于抽象数据类型,可以这样使用:

创建某一类型的变量(创建对象或者实例),并调用其方法(发送消息或请求,让它知道该做什么)。

每个具体的对象又有自己特有的状态,比如,苹果的皮是红的,梨子的皮是绿的。苹果水分少,梨子水分多等。所以,苹果、梨都是水果类,但是它们又是水果类中独立的个体,这些个体就是一个个唯一的对象,那么对象与类的关系就明了了:每一个对象都属于定义了特性和行为的某个特定的类。编程系统对待抽象数据类型与对待一般数据类型是一视同仁的,也会作类型检查等:

苹果和梨子都能吃,能榨果汁,能制作苹果罐头等。吃、榨果汁、制作罐头这属于行为(也就是方法,也就是请求),苹果和梨子都满足这些特定的请求,那么这些特定的请求就定义在接口中,而接口也是一种类型:

接口只是定义了可以向某一特定对象发出的请求,那么具体到苹果、梨子该发出怎样的请求,剥皮吃还是不剥皮,榨果汁时要注意什么,这都是具体请求该有的细节,在苹果类、梨子类中必须有这些具体的细节方法,这些代码就构成了“实现”。

三、每个对象都提供服务

不要试图把所有功能都拥挤在一个对象里,完成一项服务项目需要各个对象的配合,比如实现一个打印模块,我们可以定义一个对象专门检查配置是否正常,另一个对象定义怎样打印一张4A图纸,再定义一个对象集合,调用前两个对象,再加之自己的方法最终把图纸打印出来。每个对象都可以很好的完成一个任务,但并不试图做更多的事情。然后这些对象齐心协力去完成一项服务。

上述的“齐心协力”其实就是软件设计的基本质量要求之一:高内聚

四、访问控制

 

Java用三个关键字控制了变量及方法的访问:public、private、protected。public其他类都可以访问,private只有本类及类的内部方法能够访问,其他类不可见。protected表示只有本类及继承本类的子类可见,其他不可见。除此之外,Java还有一种默认的访问权限:包访问权限,类可以访问同一个包中的其他类成员。

访问控制的原因1:让客户端程序员(类的调用者)无法触及他们不该触及的部分。调用者只需要调用有用的方法,有些变量等是设计者为了实现内部逻辑而使用的,不需要让客户端程序员知道。如果把那些私有变量公开化,既会干扰到客户端程序员的调用思路,也可能被客户端程序员误操作而修改了状态值。

访问控制的原因2:类库的设计者可以改变内部的工作方式而不会影响到外部客户端程序员的调用。

五、组合,聚合,代码复用

代码复用是面向对象程序设计语言所提供的最了不起的优点之一。

直接用某个类创建一个对象也属于复用,下面第6行就是在复用Apple类。

将某个类的对象置于某个新类中(创建一个成员对象),也属于复用:

上例中是用Fruit、Dog合成了Test类,所以,这个概念称为:组合(composition)。如果组合是动态发生的,则称为“聚合(aggregation)”。

什么是动态发生呢?看:

第7行并没有创建Apple实例,等到11行调用时,才实例化了Apple,这就是动态发生。

组合的关系是:has-a,即:汽车拥有引擎、公司拥有员工、Test拥有Fruit、Dog。

六、继承

复制现有的类,然后添加和修改这个复制品来创建新类,这就是继承。当源类(又叫:父类、超类、基类)发生变动时,被修改的子类也会发生这些变动。

上面Circle继承了Shape,自然也就继承了Shape的color属性,以及getColor()、setColor()方法、draw()方法。在继承过来的同时,Circle修改了draw()方法,表现出自己与父类不同的地方(这一行为叫做override,即:覆盖)。当然,Circle也可以添加自己的新方法。

如果我把父类的getColor方法修改一下:

那么子类的这个方法就跟着发生了改变。

父类含有所有子类所共享的特性和行为。比如上例,color变量是共享的(color属于特性),draw()方法也是共享的(draw()属于行为)。

父类与子类有着相同的类型。

从上面代码可以看出,Circle类型同时也是Shape类型,这个很容易理解,博美是狗,泰迪是狗,圆是图形,没毛病。

理解面向对象设计的重要门槛是理解:通过继承而产生的类型等价性

使父类与子类产生差异的两种方法:

1, 添加新方法。(此时,子类与父类的关系是:is like a)

2, 覆盖。(只覆盖而不添加新方法的话,子类与父类的关系是:is a)。

七、向上转型

上面代码中,test()里面的参数为父类Shape,调用的也是父类Shape的draw()方法。当在main方法中调用test时,却传入了子类Circle对象,test方法也可以正常调用,且这时,调用的是Circle的draw()方法。

经常需要这样,把一个子类对象当做它的父类型来对待,这样做的好处是,不依赖特定类型的代码,也不受添加新类型的影响。比如,下一次你传入一个正方形子类,那么test内部就会自动调用正方形的draw()方法。你如果添加一个新类:六角形,然后把六角形对象传入test,它也能够正常调用。

面向对象设计语言采用的是“后期绑定”。当test()方法具体调用时,才能确定参数所对应的具体类型。

上述把子类当做父类型的过程叫做“向上转型,upcasting”。

容器

我们有时需要管理很多对象,我们不知道需要多少个对象,不知道这些对象能够活多久,不知道存储这些对象需要多大空间,一问三不知。

容器(集合)帮助我们解决了上述问题。我们把对象放入容器中,在任何时候都可以去扩充它。

Java中具有满足各种需要的容器。比如:List(有序的对象集合),Map(建立对象之间的关联,也叫映射),Set(每种对象只有一个,不会重复,类似于数学中的集合),当然,还有队列(先放进去的对象先出来,FIFO)、树(以任意顺序把许多对象放进该容器,当你遍历时每个值已经排好序)、堆栈(最后放进去的对象先出来,LIFO队列)等。

对象的关联比如:

把”张三”与”NAME”关联,把”17”与”AGE”关联,这样,在获取”张三”时,只需要如下:

1,不同的容器作用不同(接口不同、方法不同)。

比如:下面是Stack(堆栈)的继承层次及接口方法:

下面是Queue的继承层次及方法:

二者不在一个继承树下,且各自的方法功能不相同。实际上,Stack(堆栈)是一种后进先出的模式,只能在栈头进行插入与删除操作。Queue(队列)是一种先进先出的模式,只能在队尾进行插入,在队头进行删除。

2,不同的容器性能不同

比如:ArrayList和LinkedList。如果是随机访问一个元素,对于ArrayList来说时间是固定的,而LinkedList需要从第一个元素开始查找,直到找到目标元素,如果目标元素在容器的末端,那么就要花费更多时间。

如果是插入一个元素,对于ArrayList,插入位置后面的元素统统要往后移动一位(想想实际生活中的插队),而对于LinkedList来说,只需要把插入位置的两个对象拆开,然后把目标元素加入进来即可(想想实际生活中小朋友们手拉手的情况)。下图是LinkedList的插入与删除:

泛型,向下转型

Java中,所有对象都继承自Object,那么由向上转型规律可知,能存放Object的容器,就能存放任何Java对象。

其实容器里放置的并不是对象本身,而只是对象的”引用”,指向对象的地址。

当你把一个非Object对象(比如String)的引用放进一个容器时,由于该容器只能存放Object引用,所以,它将会强制转成Object引用。那么当你再次取出该引用时,就变成了Object引用,而不是你想要的String。如下:

虽然存入List中的是dog的引用,而把它赋值给dog2时,却报错,因为dog.get(0)取出来的是Object类型的引用。这时,就要用到向下转型。

向上转型是把子类当作父类来用,而向下转型是把父类型转换为一个更具体的类型:

比如上图,把Object引用强制转换为Dog。

向上转型是安全的,比如你可以大胆的说:苹果是水果,梨子是水果,所以,你可以大胆的把任何对象强制转成Object:

向下转型却是不安全的,你只知道它是一条狗,但是你不知它具体是什么种类:

上例把泰迪放入List,取出来时是Object,却错误的把它转换成博美,结果发生了错误。

为了避免上面种种风险的发生,Java中引入了泛型:

如上图,明确说明List狗窝中只能放泰迪,那么你放入博美就会直接报错。

如上图,我已经知道List狗窝里面睡的是泰迪,你取出来把它喊成博美,那么也会报错。

对象的生命周期

出生:

当你每次new一个对象时,Java就动态地在一个称为“堆”的内存池中创建一个对象。由于是动态的,所以,直到运行时才能知道要创建多少个对象,对象的生命周期是什么,以及对象的具体类型是什么。再搬出前面出现过的一段代码来加深对“动态”的了解:

上例中,直到运行test()时才会创建Apple实例。

死亡:

Java的垃圾回收机制会自动发现对象什么时候不用了,然后去销毁它,以达到释放内存的目的。

Java判断某个对象是否可以回收是一件复杂的事情。比如,一般情况下,创建一个对象,会在堆中生成一个对象,而会在栈中放一个该对象的引用(一个数字,指向这个对象在堆中的地址),垃圾回收器有一种早期策略,每生成一个引用,计数器就会+1,而每减少一个引用,计数器就会-1,当发现计数器为0时,说明该对象可以回收了。如下图:

图中第四步,per2指向了per1引用的地址,那么就没有引用指向age=20的那个对象了,于是,那个对象会被垃圾回收器回收。

十一异常处理

异常是一种对象,当程序发生错误时,它从那个错误点“抛出”,然后由该错误对应的专门的处理器“抓住”。所以,如果代码是正常的,异常代码将不会发生。

有些异常是在运行的时候才能发现的,主要是由于程序员的失误造成的,这类异常叫做“运行时异常”,比如:

你明知道test不能转成整数,还非要转,运行时就会报错。

还有一种异常,叫“非运行时异常”,就是运行前就该有所防范的,比如想从某个路径下加载一个文件,这种情况下,就有找不到这个文件的可能性,那么,你必须做出防患于未然,可以抛出异常:

也可以捕获异常:

十二、并发编程

为了提高响应能力,我们想把一个任务分成多个子任务独立的运行,让他们一起干活。这些独立运行的子任务就是”线程”,而“一起干活”就是“并发”。

实际上,在单一处理器环境中,线程之间是轮番交叉运行的,由处理器来分给每个线程时间。而在多处理器上才存在真正的”一起干活”,即“并行”。

多线程并发完成一项工作的过程中,资源共享就带来隐患,比如桌子上有一个粉笔(资源),两个小朋友(线程)同时伸手去拿粉笔(抢占资源),那么就会打起来。所以,就要有一种机制,当一个小朋友要去拿粉笔时,先把粉笔保护起来(加锁),等这个小朋友不用了,再释放锁,另一个小朋友才可以用粉笔。

更多内容请关注:

时间: 2024-11-10 01:31:36

万物皆对象的相关文章

Python中万物皆对象?的理解

在很多地方都看到有过这样一句话,但是对象这个词的理解依然停留在谈朋友那个对象上-- <python中的对象的理解> python中一切皆为对象,一个对象的特征也称为属性(attribute).它所具有的行为也称为方法(method) Python中的对象包含三要素:id.type.value 其中id用来唯一标识一个对象, type标识对象的类型, value是对象的值 is判断的是a对象是否就是b对象,是通过id来判断的 ==判断的是a对象的值是否和b对象的值相等,是通过value来判断的

重新认识java(一) ---- 万物皆对象

如果你现实中没有对象,至少你在java世界里会有茫茫多的对象,听起来是不是很激动呢? 对象,引用,类与现实世界 现实世界里有许许多多的生物,非生物,跑的跳的飞的,过去的现在的未来的,令人眼花缭乱.我们编程的目的,就是解决现实生活中的问题.所以不可避免的我们要和现实世界中各种奇怪的东西打交道. 在现实世界里,你新认识了一个朋友,你知道他长什么样,知道了他的名字年龄,地址.知道他喜欢干什么有什么特长.你想用java语言描述一下这个人,你应该怎么做呢? 这个时候,就有了类的概念.每一个类对应现实世界中

又一次认识java(一) ---- 万物皆对象

假设你现实中没有对象.至少你在java世界里会有茫茫多的对象,听起来是不是非常激动呢? 对象,引用,类与现实世界 现实世界里有许很多多的生物,非生物,跑的跳的飞的,过去的如今的未来的,令人眼花缭乱.我们编程的目的,就是解决现实生活中的问题.所以不可避免的我们要和现实世界中各种奇怪的东西打交道. 在现实世界里.你新认识了一个朋友,你知道他长什么样,知道了他的名字年龄.地址. 知道他喜欢干什么有什么特长.你想用java语言描写叙述一下这个人.你应该怎么做呢? 这个时候.就有了类的概念. 每个类相应现

大话JS面向对象之开篇万物皆对象------(ATM取款机引发的深思)

一,总体概要 OO(面向对象)概念的提出是软件开发工程发展的一次革命,多年来我们借助它使得很多大型应用程序得以顺利实现.如果您还没有掌握并使用OO进行程序设计和开发,那么您无疑还停留在软件开发的石器时代.大多数编程语言,尤其是近年问世的一些语言,都很好的支持了面向对象,您可能对此了如执掌,但是一些语言在OO方面却无法与其它高级语言相比,在这些语言上进行面向对象程序设计和开发会有些困难,例如本文要讨论的JavaScript.JavaScript是一门古老的语言,但是随着近期Web2.0 技术的热捧

万物接对象?!

想必学过java的童鞋都见过这句话"万物皆对象".一个对象,只要你能拿得出来,那他就继承自Object... 真的是这样吗...我要来试试...... 仔细想想不禁不要问...接口呢?接口继承自Object吗? null又如何呢? 我们来验证一下: 接口: 接口能继承Object吗? 很明显,和我们预期的一样,不能..... 2.接口中能调用Object的方法吗? 居然可以耶,在eclipse中我们可以发现toString()方法来自Object 3.Collection难道继承了Ob

DAY10-万物皆对象-2018-2-2

许久没有写了,虽然每天都有在学,但是学的东西也少了,后面难度慢慢加大,学习速度也是变慢了.这是许多天积累下来的笔记,从第一次接触对象,到慢慢去了解,现在处于还待深入了解的状态.万物皆对象,那是不是说没有对象的小伙伴不必担心了呢? 万物皆对象 终于到了对象这里.面向对象程序设计(简称OOP),Java是完全面向对象的. 一.使用面向对象思想描述现实世界. 基本步骤: 1.发现类 如下图:可以将下图的人分为几类 人类/科学家类/演员类/逗比类 2.找出属性(名词) 姓名.性别.职业.年龄.爱好--

第二章:一切皆对象。(一)

2.1.用引用操作对象. 1.一个形象的比喻:在java中,一切皆对象.但是操纵的标示符实际上是对象的一个“引用”(reference).可以想象成一个遥控器(引用)操纵电视机(对象). 想要换频道或者调整音量,实际操纵的是遥控器(引用),再由遥控器来操纵电视机(对象). 2.有5个不同的地方可以存储数据: 1.寄存器:这是最快的存储区.它位于处理器内部.寄存器的数量极其有限.根据需求进行分配,不能直接控制. 2.堆栈:位于通用RAM(随即访问存储器)中,堆栈指针若向下移动,则分配新的内存:若向

Java之路(一) 一切皆对象

Java语言假设我们只进行面向对象的程序设计,即在开始用Java进行设计前,我们需要将思想切换到面向对象的世界中. 1.用引用操纵对象 每种编程语言都有自己操纵内存中元素的方式.是直接操纵元素还是用某种基于特殊语法的间接表示来操纵对象? Java中将一切都视为对象,这样就可采用较为单一固定的语法. 虽然将一切都看做对象,但操纵的标识符实际上是对象的引用. 拥有一个引用,并不一定与一个对象相关联. 2.必须由使用者创建所有对象 1).Java内存分配 五个地方可以存储数据: a.寄存器.位于处理器

万物皆可“互联网+”

在你的眼中,"互联网+"会给你的专业带来哪些新变化?(形势与政策小论文) 万物皆可"互联网+" 2015年3月5日十二届全国人大三次会议上,***总理在政府工作报告中首次提出"互联网+"行动计划. 放眼我国的互联网发展历程,从1987年,北大钱天白向德国发出第1封电子邮件--当时中国还未加入互联网.到1989年, 中国开始建设互联网 --- 5年目标 ---国家级四大骨干网络联网.1994年, 中国终于获准加入互联网并在同年5月完成全部中国联网工