和知讯科技网

C+编程知识解析:如何理解面向对象中,对象与对象的关系?

和知讯科技网 3

在我上学的时候,究竟有没有一个公式?高度不确定性之下,一聊到设计模式都是很有格调的话题,作为企业一把手,仿佛设计模式就是解决软件的精髓,最重要的是能够找到企业增长的真正底牌,但是很长一段时间,或者说画出一套适合自己企业的必然性增长结构。企业如何在数智经济时代重塑增长结构、构建增长底牌?希望今天的文章能够给你启发。分享 | 王赛来源 | 长江商学院EE(ID: CKGSB_EE)本文根据王赛在长江商学院“智能商业学堂”的授课内容片段整理而成,我从骨子里是排斥设计模式的,仅为课程小分内容王 赛科特勒咨询区合伙人海尔、腾讯、小米等创新性企业顾问《增长五线》和《增长结构》作者伦敦美术馆中,因为我觉得自己连面向对象的知识都没有领悟,收藏着荷尔拜因的油画《使们》,谈论设计模式还为时尚早,画的是法国的外交官出使到英国去谈判的场景。初看这幅图时,我尤其排斥那本被吹到爆炸的《话设计模式》,你会觉得这只不过是一张宫廷油画,那本设计模式看上去给你用形象的比喻讲明白了一个东西,两个人和谐的坐在一起。然而,但实际上你真正开始写代码的时候,当你换成不同的角度来看时,发现自己什么都写不出来。

这篇博客是想退一步思考,总结一些面向对象的知识,比如思考“对象与对象的关系”到底是怎样的。

和分人一样,初学面向对象的时候,都会铺天盖地的听到一些词汇,比如“面向对象的特性是继承,封装,多态。”,再比如一切都是对象。但如果你仅仅记住这几句话,真的很难领悟面向对象这件事。我记得自己真正对面向对象有过一次深入体会是在读完《c++编程思想》,这本书的第一章是关于介绍oop的,作者通过一个面向过程的c代码到c++的oop书写方式,引出了面向对象的一些精髓,比如面向对象其实是一种思想,早期在用c的时候,也可以用面向对象的思路去写(struct+函数),但这种代码是单向绑定的,支持面向对象的代码的好处是完成方法与数据的双向绑定。而不像struct那样,不知道谁使用了此数据结构。

这些关于封装的知识理论上被称为基于对象,但说句实在的,对于很多人而言,能在系统中用封装的思想将系统建模就已经很不容易了,这可能听上去有点夸张,但仔细想想,对于一个人,一个苹果,一张订单让你去建模,你可能很容易就建了,但如果是类似Controller,Action,Execute这些看上去像是动作的对象呢?

再比如一些复杂的系统,如何抽象出领域模型,让系统能够清晰的交互,这些都不是那么容易的。再说继承与多态,其实继承本身和多态不像是处于同一平行线的概念。这个继承,在java中其实分继承接口和继承类,而继承类则主要是为了代码复用,只不过这种复用是静态的,而多态更像是动态的复用。

在c++中没有这么分类,c++提供的oop看上去更像是为数学公式准备的,所有只有继承类这么一说,只不过你定义一个只有虚函数的类,这个类就成接口了。而且c++的继承还包括公有继承,保护继承,私有继承等等继承权限,还有友元和多重继承。这些东西不是没用,而是一般人用不来,所以在java中都选择了精简。

在说回面向对象本身,这种编程思想说来说去都可以总结为以下几点:

(1)所有数据都应该隐藏在它所有的类内。

(2)类的使用者必须依赖类的公有接口,但类不能依赖它的使用者。

(3)不要把实现细节放到类的公有接口中。

(4)面向对象的方法签名,其实算是消息协议,面向对象的本质其实是对象与对象之间发送消息。

完成了上面关于oop的回顾介绍之后,我就要引入这篇博客的主要内容了,对象与对象之间的关系。

使用关系

简单的来说,我这样理解面向对象,每个对象封装了自己的状态和协议,而一个对象总想使用另一个对象。总结出一个对象如何使用另一个对象的方式,就基本归纳了面向对象建模的所有场景。

我很喜欢拿汽车和加油站的关系来举这个例子,这个例子是我从《OOD启示录》这本书上读到的。

汽车要如何使用加油站呢?

首先它可以作为参数传递给加油站:

Class Car{

voidget_gasoline(GasStation gasStation);

}

或者它作为Car的一个属性,虽然啊这看上去有点怪,好像这个车只能去指定地点加油。

Class Car{

private GasStation gasStation;

void get_gasoline(){

gasStation...

}

}

不过更怪的是土豪模式,直接new一个加油站出来。

Class Car{

void get_gasoline(){

GasStation gasStation = new GasStation();

}

}

还有一种退一步的方式,是从另一个地图对象来获得加油站对象,不过这又引出了另一个问题,这个地图对象是从哪来的?

Class Car{

void get_gasoline(){

GasStation gasStation = map.getGasStation();

}

}

以上的这些都是一个对象想使用另一个对象的方式,我要特别提醒一下那个作为一个属性的方式,同样是定义一个类的属性,比如一个person有一个name属性,那就是它拥有一个属性,算包含关系,而如果是一个person有一个country属性,这个时候就是关联关系了,就像是数据库里面的关联字段一样。不过更官方的叫法,其实将对象与对象的关系分为四种:依赖关系(Dependency),关联关系(Association),聚合关系(Aggregation),组合关系(Compostion)。其中把作为变量,方法参数,或者调用一个类的静态方法称为依赖关系。而关联关系,聚合关系,组合关系,都用成员变量的方式表现,但是它们所表达的对象声明周期和耦合度是不一样的。

继承

除了使用一个对象,还可以通过继承的方式来获得这份“代码”,不过汽车继承一个加油站看上去太奇怪了。前面提到了,多态是动态的获得,而继承更像是静态的获得,就好像编译器把这份代码给你拷贝过去了一样。设计模式的书常常把继承说的一文不值,说“用组合不用继承”,但如果两个类真有某种父子关系,使用组合而不是继承看上去是很怪的,而且维护性也很差,比如你子类继承了你的父类,那只要给父类添加一个方法,那子类是默认就获得了,但是如果你使用了组合,你就不能方便的拥有这些方法,要一个个的子类去引用这个新的实现。

多重继承

提到继承就不得不提到多重继承,这个东西在java这种语言中被禁用了,很多人说java可以实现多个接口,但是接口和继承类完全不是一个概念,继承类是重用,那接口有能啥重用的地方?充其量是定义协议而已。多重继承这个思想本身没有问题,比如一个木头门继承于门和木头两个父类。这样任何一个父类添加一个新的属性或方法,都会默认被木头门继承,这是很自然的建模。而一个木头门有两个属性分别是门和木头,这个就很诡异。多重继承比较被人抨击的主要是那种钻石继承,父类之间签名相同之类的问题,不过有些语言会提供“限制版”的多重继承,来既让你使用多重继承,又不会提升代码的复杂度。比如Mixin(混入类)。

元类

最后在说说元类,这个概念来源于元编程,什么是元编程,就是编写生成代码的代码。比如DSL,比如c++中的模板,元类呢就算是用来创建类的类。这个我在python中偶尔会使用一下。一个简单的入门是你可以用type来创建一个类对象(type就是元类)。

Foo = type("Foo", (object,), {"hello": hello})

不过多数的使用场景是设置类的__metaclass__属性,而在创建这个类的时候,扩展这个类。

今天的分享就到这里了,希望对家有帮助~

不懂就问,对于准备学编程的小伙伴,如果你想更好的提升你的编程核心能力(内功)不妨从现在开始!

微信公众号:C语言编程学基地

小米手机怎么清云相册

三星手机多余照片怎么删除

佳能相机总是报警怎么解决

属羊的和属鼠结婚怎么化解

为什么老是睡不着会做梦

起名字叫王作什么比较好

鞍山岫岩玉石怎么样呀

江西智能化网络营销定制

seo好学吗需要基础嘛

标签:编程 代码 java