首页 > 代码库 > 面向对象
面向对象
面向对象
Java是支持面向对象编程的语言,java设计思想参考java之父James Gosling的一次谈话 http://www.artima.com/intv/gosling1P.html 。设计简单,易于理解,多用于开发Internet
应用软件。90年代的许多软件开发思想得利于Smalltalk语言。
本文试图从多继承、封装、多态、闭包的实现来说明几种语言面向对象编程的特点。包括:不同访问权限,如私有、公有;类属性(静态)与对象属性(只属于每个对象);接口、抽象方法;常量、变量。如果你是某种语言的专家,请指正。
动态语言? | 作用域 | 类与对象 |
JavaScript | var声明为当前作用域,否则为全局。 静态类型通过语言内置原型prototype字段,隐式支持。包括构造器constructor | 动作方法只支持封装function,json可作为数据类型封装。 ECMA6支持class 规范:接口的实现通过巧妙的编程设计来实现。JS的设计非常简单,可读性和功能很强大 |
Python | __ 下划线声明为私有字段,否则为共享字段 方法可以定做在类中也可以在类外(文件中)。类外方法可以作为静态方法,另外类方法、接口、抽象方法通过注释实现。 | class关键字支持。def关键字定义方法。有构造方法和析构方法。以及类似静态构造方法new方法,只执行一次,在所有方法之前执行。 通过人工手段实现规范,非原始支持这些规范。 |
PHP | 已经启用var关键字,通过其它关键字声明作用域,语法类似Java。可读性很强。 变量作用域关键字支持全面 | class 等支持良好。 |
编译语言? | ||
Go | 以C语言为原型。通过首字母大写为作用域。通过包来区分一组功能,没有类的概念。main方法为程序入口,不同操作系统编译为不同的可执行程序。 | 方法、接口、数据结构(类)等是同一个级别的。在Java中方法属于类,是隶属关系不平等。 新的编程思路的设计语言。非常有趣。 |
Scala | JVM平台语言,高阶函数支持。语法略显臃肿,或者说这样让面向对象设计的思维负担减轻(这个懒是不能偷)。支持太多,或者说不是好事。 | class有一个伴生对象用Object关键字声明(单例设计)。可直接声明函数,函数不同于方法,方法定义类或者伴生对象中。伴生对象即静态支持。 |
Java | 通过关键字声明作用域,static为所有对象共享。可读性非常好。规范性强,需要较多的设计技巧,良好支持企业级多团队开发。 | C语言系列语言。 |
Javascript
关于闭包,最简单的描述就是 ECMAScript 允许使用内部函数--即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。————百度百科。
本文没有使用ECMAScript 6的新特性。如class与extends。
对于JS面向对象的详细了解,请点击这里。
在文件中声明作用空间,类似java中的package。目的是区分
类模板,复用此类模板
在任意一个*.html文件中测试,直接用浏览器打开即可。
注释掉上面的测试数据,上面的属性为对象私有。下面介绍类属属性。对象共享类似静态属性、静态方法在javascript中的设计。JS中属性可以动态按需增加或删除。var声明变量为当前作用域类似private,但不是访问限制。不加代表全局作用域。
这里的原型只能通过类(即方法名).prototype来使用。
继承
在Person中加入原型属性,保持父类原型非空有意义。
- 子类原型保存父类模板以及原型,但用父类构造方法且保存了值。这适用某些情况。
- 模板继承,解决了上面继承值问题。但不继承原型。
Teacher类继承Person类
ECMAScript规范给所有函数都定义了Call()与apply()两个方法,call与apply的第一个参数都是需要调用的函数对象,在函数体内这个参数就是this的值,剩余的参数是需要传递给函数的值,call与apply的不同就是call传的值可以是任意的,而apply传的剩余值必须为数组。
- 把继承抽象成工具方法,继承原型而不影响父类。但仍需要子类绑定模板。
prototype会形成原型链,对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。上面:子类sub的原型是F的对象,同时F也有自己的原型,F的原型是父类sup的原型(对象)以此类推到Object,Object的原型对象为null。
这里需要注意的是所有的实例对象共享constructor,而constructor是prototype的属性,所以在修改原型对象的时候一定要还原构造器。
这里相等于JM.Sup.call。extend方法中的F空函数是必要的,否则会在call中递归调用发生异常。
测试
如果要实现多继承,可以定义supClass数组或维护对应继承数量个变量。
接口实现
这里模拟写一个数组实现的集合
闭包实现
这是例子假定不同浏览器有不同的显示策略。根据不同的浏览器标示,匹配不同的配置文件。返回结果是个单例。
单例方法,模拟浏览器标示。
不同配置策略
单例实现
测试
PHP
PHP 语法
定义一个类模板,演示封装。其中有类常量,全局常量,超全局常量。静态属性、静态方法。
新建个文件Package.php,用于封装的测试
$this 关键字指代对象,self指本类,parent指父类。类属访问用::,否则用->。
var关键字在PHP后续的版本不推荐使用了。
构造方法
析构方法
这个简单的类模板,演示了作用域public、protected、private 修饰的成员或者方法。类常量用关键字const,一般大写,它的涵义表明了作用域。全局常量用define(name,value)。Php中常量跟变量有区别。下面的子类演示了静态变量、静态方法的定义。
测试方法
静态变量属于类,可以改变。Php中常量不允许修改。
在另外一个php文件中写测试,require_once 引入要测试文件。
析构方法执行
接口与抽象类
PHP中接口与抽象类与java很相似,区别:不同的东西,抽象类不能实现接口。
接口
实现类码农先生
抽象类
抽象类的实现类,final 关键字与java相似,但只作用类
测试,hi(方法名,参数列表),hi方法并没有定义。
Python
*.py文件,第一行说明文档字符集。这是一个单例例子。类属私有变量、公有变量、方法,对象绑定变量、方法。构造、析构方法。
__field表示私有变量,否则为公有。
上面的getName传入对象,类似java getter方法。__new__在构造方法前执行,返回实例对象。这些在类中直接定义的方法都是对象方法,不能用类调用。
内部类的__call__使类变成可调用的函数。函数可以直接在外部定义,下面会解释。
类方法、静态方法要加对应注解,区别在于第一个参数是不是类的对象实例。这里say()方法应该是表达,赋值显得有些语言不是很准确,只是希望多表达一些功能。
测试及结果
这里的例子为了说明python的封装。
#优势 动态添加属性 object.field=value 删除del
接下来是继承、接口规范的测试。
子类没有重写构造方法时会继承哪个?默认继承第一个,如果我们没有注意继承顺序或者分别需要不同方法,反而需要显示重写。
接口或者抽象类定义了必须实现的规范。Python中的规范是通过人有意识来实现。接口、抽象类是通过编程实现的。如果通过功能约束则需要较高的编程能力。
这是一个接口的例子,如果不实现会报:AttributeError: Foo instance has no attribute ‘bar‘。
依赖zope接口规范库,需要pip、Twisted 。
抽象类,不实现:TypeError: Can‘t instantiate abstract class Worker with abstract methods talk
Scala
Scala方法和函数是有区别的。详细介绍点击这里。
本文中的目录结构
下面的例子介绍scala实现单例的过程,其中涵盖scala的编程特点。
在包oop.example下新建一个scala文件。
在这个文件中写个Worker类,类上是个主构造方法,访问权限是私有。参数:名字和外号。
定义个从构造方法,没有具体意义。
重载toString()方法
在同一文件中定义伴生对象
定义一个静态私有常量instance,其它不重要用于演示的成员。
获取单例对象的方法。至此一个单例就完成了。
通过Worker既能访问伴生对象(静态)方法、属性,通过getInstance()也能获取类单例对象实例。
Scala中的接口和继承。
Scala是单继承,否则错误提示:class Other needs to be a trait to be mixed in。
Scala可以继承多个特质,而特质类似java8中接口,可以定义多个方法,从而实现多继承。其它可以参照java实现多继承。
在package oop.example下任意新建个scala文件。
这里定义特质 Person,Studnet
特质用trait关键字,: 冒号后面指返回值,Unit同void。
抽象类Coder继承多个特质。
这里函数一般定义 val 函数名 = (参数列表1-22个) => 函数体,不用声明返回值类型,因为是确定的。
接下来介绍scala的package object对象。详情点击这里。
Package提供了一个命名扩展。会首先编译,如果出错,其它scala文件将执行不了。
则可以这么使用
结果:
用type 给oop.example.Me起个别名,这里是因为路径太长。目的如果Me路径改变了,通过原先路径(别名)照成访问。
在package scala中可以定义class或object对象。
下面是个scala高阶函数的例子。Object类型不用对static考虑,减少设计负担。
这是一个延时执行方法例子。参数是方法。
object Xxx 中main方法执行
结果
下面是个高级函数例子
applyX中f(v),f为方法,v是参数。
方法可以没有参数列表即(),函数必须有()。
Go
Go语言之父,设计go语言设计目标的演讲。点击这里。或者复制下面链接http://www.csdn.net/article/2012-07-05/2807113-less-is-exponentially-more。
核心思想:Less can be more!并行性,类似软管拼接的编程体验。
Go语言语法简单,例子中介绍
声明一个接口,这个接口是方便在hi.go中测试。
定义通道syn保证Init方法与Test方法同步执行
所有的测试文件在src/oop目录下,在hi.go中引入,
要测试的go语言特性。
要测试的几个文件都实现了oop.Test接口
Go语言公有的访问权限是首字母大写,否则将编译报错
闭包特性
继承例子
Go继承是通过组合
Go并发特性
一个并发池的例子
通道概念
一个死锁例子
通过go 并发解决这个问题
或者改为缓存通道
Java实现多继承
Java一般通过组合和接口实现多继承。因为接口是可以多继承的,在接口的实现中调用其它类对象的方法。
定义两个接口分别是Action和Art,表示物理上的行为和隐含的需要理解感受的行为。
自然界的动物继承Action行动,Art感染力。
人类,直接实现Animal接口实现多继承。但这样需要自定义实现。
另外一种使用场景,一些方法是确定的,另外一些不确定。所有鸟的例子。
具体哪种鸟不一定,比如会抽烟、会唱歌的鸟。
一只参与京剧表演的老鹰
一个非常善于学习的人,会多种技巧。
Java闭包实现
java闭包是通过接口和私有内部类实现的。利用java的运行时多态,接口引用实现类的。返回实现接口的私有内部类实例实现的。
接口Worker表示所有的工作者,方法work表示不同的工作形式。
软件程序设计者
软件开发者,熟练get各种技能
资深Coder除了进行简单必要的软件设计,还要有其它技能:交流、管理。这个Coder的黑科技是加班。
这个已经能访问到私有对象。
一个方法多种实现
面向对象