zoukankan      html  css  js  c++  java
  • Ruby学习之对象模型

    这两周工作内容较多,平时自己也有点不在状态,学的东西有点少了,趁着现在还有点状态,赶紧复习一下之前学习的Ruby吧。

    Ruby是我真正开始接触动态语言魅力的第一个语言,之前虽然也用过且一直用perl、python等脚本语言,但是只是作为unix shell的扩展(和工作有关),没有真正地审视动态语言的哲学。是《Ruby元编程》这本书,好像给我打开了一扇新世界的大门,书中介绍的每一个特性都让我兴奋地几乎跳起来,这就是学习的魅力吧。

    Ruby语言初探

    由于是第一个Ruby的随笔,先简单介绍一下ruby的语法规则吧。ruby的语法和python有点类似,但是不要求严格缩进(当然没什么特殊情况缩进是必须的),所以用end关键字来表示结束。

    说实话还没有深究过ruby中的每一个变量类型,但是有一点是确定不变的:动态,强类型。所谓的强类型就是一个变量只能只一种类型,不能变成其他类型,而在实际使用中,你会发现一个变量是可以自由隐式转换的,比如

    var=1

    var=“string"

    不会有任何问题,但是这并不表示ruby就是弱类型语言。和python类似,ruby中的变量其实就是内存的引用,当隐式改变一个变量的类型的时候,其实是新建了一块新的内存,并且将变量名指向新的地址,作为新值的引用,而原来的旧的内存内容当他的引用次数变成0的时候,就会被系统的垃圾回收机制适时地回收掉。(此处用python的内存原理类推了一下,并没有求证,如果有错误,希望大家多多提出)

    ruby中用小写字母或者下划线开头的关键字作为变量名,以@开头作为实例变量名,用class关键字定义类,module关键字定义模块,def关键字定义方法,initialize方法来构造一个对象,return关键字返回值,用.调用方法等,没有任何很奇怪的语法,一切看起来都是那么自然。

    Ruby中的对象

    Ruby中到处都是对象,每一个对象都来自于某一个类,同时这个类可能继承于某一个父类。对象又可以称为类的实例,对象的属性,也就是类的实例变量,存放在对象中,而对象的方法,也就是类的实例方法,存放在类中。所以同一个类下的不同实例可以共享方法,但是实例变量确是不共享的。每一个类都继承与Object类,Object类中存放诸如class()(查看对象的类)等方法,而Object又是继承自BasicObject类(白板类,创建继承自白板类的对象可以消除之前可能存在的所有方法)。每一个对象的类都是Class,Class只是一个封装了new()等方法的Module......

    说起来有点拗口,我大致画了一下示意图(实线表示class,虚线表示superclass):

    NewImage

    Ruby中的方法

    当你调用一个对象的方法时,系统会从该对象的类中查找是否有该方法,如果没有找到,则会依次到上一级父类中查找,直到找到该方法,如果没有找到,则会调用method_missing()方法,调用幽灵方法,或者报出调用错误的信息。可以调用ancestors方法,查看当前对象的祖先链(即上述查找过程的链结构,特别的,在Object之后,会查找Kernel模块,这是由于Object包含了Kernel模块,Kernel中包含print等方法),Ruby就是在祖先链上依次查找方法。

    找到方法后,自然要执行了,然而按照以上所说,方法的查找需要经过一个祖先链,那么在调用这个方法的时候又是如何确定接受者的呢?在Ruby中,每一行代码都会在当前对象中执行,这个当前对象就是self,没有明确指定接受者的方法都在self上调用

    事实上,每个Ruby脚本执行时,都会创建一个main对象作为当前对象,此时,self就是main(main又可以称作顶级上下文,正如python中的顶格书写的代码,而不是c,c++中入口函数的概念)。

    Ruby中的私有方法也和c++中有所不同。private关键字后面的方法只能被隐含接受者调用,(又由于调用方法时,如果接收者不是自己,则必须明确指定一个接收者,上述下划线文字)所以私有方法只能被自身调用。检查私有方法调用是否合法,只需检查是否指定了接收者(否)以及当前的self是谁。

    扩展:在Ruby中,有种邪恶的方式可以得到任何规则的豁免来访问任何方法,包括private,即send方法。

    Ruby中的类操作

    在Ruby中,用class关键字定义一个类, 如果这个类不存在,那么会创建这个类,如果这个类存在了,则会对已有的类添加方法、属性等。这个操作对自带的类同样有效。如书上的一个例子,去除字符串中非字母、数字、空格的其他符号。想到的是一个用正则表达式来处理的方法:

    def to_alphanumeric(s)

        s.gsub /^ws/, ''

    end

    在Ruby中,可以“打开”String类,并且在类中直接添加该方法:

    class String

        def to_alphanumeric

            gsub /^sw/, ''

        end

    end

    于是在String中多了一个新的方法to_alphanumeric。

    ps:这是我第一次知道可以有这样的定义方式,这让我感到耳目一新,就像开了一扇窗,外面全都是新的景色。

    “打开”类添加方法的操作看起来很酷,但是仔细思考的话,其实是存在一定问题的:如果在String中,已经存在了to_alphanumeric方法,那么调用时是不能确定调用到哪个方法的。(截止到写这篇随笔的时候,我还不是很清楚在Ruby中实现C++的多态,或者是override等方式是什么样子的)

    Ruby中的常量和模块

    和python类似,用大写字母开头来表示一个常量。常量只在当前作用域下有效,类似于目录树的结构,其他作用域下的同名常量就像是不同目录下的同名文件,是不相关的。

    从随笔开始的示意图中,Module是Class的superclass,其实Module(模块)就是一些实例方法的集合,和Class就是封装了若干功能的Module(如new()方法)。Module和Class非常类似,但是使用又截然不同,当需要被继承或者实例化的时候,应该选用Class(superclass()方法和new()方法),而当需要被其他地方包含(include、import)时,应该使用模块。

    模块就像是目录,模块中的不同常量(方法或者属性的引用)就可以看成是文件,常量和模块组成一个类似文件树的结构,调用时用双冒号来表示路径(::)。用加上路径的显示方式可以唯一确定到常量的位置,这就是命名空间的概念。

  • 相关阅读:
    Java程序:从命令行接收多个数字,求和并输出结果
    大道至简读后感
    大道至简第一章读后感Java伪代码
    Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
    声明式验证超时问题
    Error message when you try to modify or to delete an alternate access mapping in Windows SharePoint Services 3.0: "An update conflict has occurred, and you must re-try this action"
    Upgrading or Redeploying SharePoint 2010 Workflows
    Upgrade custom workflow in SharePoint
    SharePoint 2013中Office Web Apps的一次排错
    How to upgrade workflow assembly in MOSS 2007
  • 原文地址:https://www.cnblogs.com/lyon2014/p/4395247.html
Copyright © 2011-2022 走看看