ruby对象是严格封装的:只能通过定义的方法访问其内部状态。方法使用的成员变量在对象外部不能直接访问,不过可以通过getter、setter等访问器方法(accessor),使他们看起来好像是直接访问的。

与对象状态的封装性相反,ruby中的类非常开放。每个ruby程序都可以为现有类添加方法,而且也可以为单个对象添加“单键方法(singleton method)”。

创建类

Classes are created in Ruby with the class keyword:
class Point
end
Like most Ruby constructs, a class definition is delimited with an end. In addition to
defining a new class, the class keyword creates a new constant to refer to the class. The
class name and the constant name are the same, so all class names must begin with a
capital letter.
Within the body of a class, but outside of any instance methods defined by the class,
the self keyword refer

class关键字还创建了一个常量用于引用这个类,这个常量名与类名相同,因此所有类名必须以大写字母开头。(因为常量名必须以大写字母开头)。
写成class a会报错:

class/module name must be CONSTANT

跟绝大多数ruby语句一样,class是一个表达式,class表达式得到值等于类定义体中最后一个表达式的值。一般而言,类的最后一个表达式都是一个用于定义方法的def语句,def语句的值总是等于nil。

实例化一个Point对象

p = Point.new
The constant Point holds a class object that represents our new class. All class objects
have a method named new that creates a new instance.

常量Point代表了类对象,所有的类对象都有一个new方法。
We can’t do anything very interesting with the newly created Point object we’ve stored
in the local variable p, because we haven’t yet defined any methods for the class. We
can, however, ask the new object what kind of object it is:
p.class # => Point
p.is_a? Point # => true

初始化

通过initialize方法实现

class Point
def initialize(x,y)
@x,@y=x,y end
end

这里定义了一个实例方法,当一个实例方法被调用时,self的的值就是代表实例。

类对象的new方法在创建一个实例化,自动调用该实例的initialize方法,传给new方法的所有 参数被传递给initialize方法。

除了被Point.new自动调用外,initialize方法会自动成为类的私有方法。对象自身可以调用initialize方法,不过不能显式对p调用initialize来重新初始化其状态

定义to_s方法

任何自定义的类都应该定义一个to_s方法,这在调试时非常有用。下面显示如恶化为Point定义这个方法。

class Point
def initialize(x,y)
@x,@y=x,y end def to_s
"(#@x,#@y)"
end end

我们就可以调用

puts p

Accessors and Attributes 访问器和属性

定义getter:

    def x
@x
def y
@y

如果想要Point类成为一个可变类mutable,可以增加setter方法

class Point
def initialize(x,y)
@x,@y=x,y end def to_s
"(#@x,#@y)"
end def x;@x;end
def y;@y;end
def x=(value)
@x=value
end
def y=(value)
@y=value
end end

可以这么调用:

p=Point.new(1,2)
p.x=0
p.y=0

一旦定义了像x=这样的写者方法,你可能会试图在实例方法中使用它们。也就是说,你想用x=2来隐士调用x=(2),而不再用@x=2.不过这是不行的,x=2只会创建一个新的局部变量。

这对新手是一个常见的错误。只有当对一个对象使用使用赋值表达式式,才会调用它的写着方法。如果你希望在定义写者方法的类中使用这个写者方法,则要通过self显式调用它,比如:self.x=2。

This combination of instance variable with trivial getter and setter methods is so common
that Ruby provides a way to automate it. The attr_reader and attr_accessor
methods are defined by the Module class. All classes are modules, (the Class class is a
subclass of Module) so you can invoke these method inside any class definition. Both
methods take any number of symbols naming attributes. attr_reader creates trivial
getter methods for the instance variables with the same name. attr_accessor creates
getter and setter methods. Thus, if we were defining a mutable Point class, we could
write:

Module有attr_reade和attr_accessor方法。因为所有的类都是模块(Class类是Module的子类),所以可以在任何类的实例中调用这些方法。每个方法接受任意数目的符号(用作属性名)作为参数,atrtr_reader为给定名字的实例变量创建同名的读者方法,

定义可变的类:

class Point
   attr_accessor :x, :y # Define accessor methods for our instance variables
end

定义不可变的类:
And if we were defining an immutable version of the class, we’d write:
class Point
   attr_reader :x, :y # Define reader methods for our instance variables
end

Each of these methods can accept an attribute name or names as a string rather than
as a symbol. The accepted style is to use symbols, but we can also write code like this:
attr_reader "x", "y"

attr_reader和attr_accessor方法可以为我们创建实例方法。这是元编程的一个例子。他展示了ruby的一个强大的特性。注意attr这些方法在类的定义内被调用,这使得他们仅在类定义时执行一次。在这里没有效率方面的问题:这样创建的读者和写者和硬编码出来的方法是一样快的。

Defining Operators定义操作符

We’d like the + operator to perform vector addition of two Point objects, the * operator
to multiply a Point by a scalar, and the unary – operator to do the equivalent of multiplying
by –1. Method-based operators such as + are simply methods with punctuation
for names. Because there are unary and binary forms of the – operator, Ruby uses the
method name –@ for unary minus.减号有一元的和二元的。-@代表一元的。 Here is a version of the Point class with mathematical
operators defined:

class Point
attr_reader :x, :y # Define accessor methods for our instance variables
def initialize(x,y)
@x,@y=x,y
end def +(other) # Define + to do vector addition
Point.new(@x + other.x, @y + other.y)
end def -@ # Define unary minus to negate both coordinates Point.new(-@x, -@y)
end def *(scalar) # Define * to perform scalar multiplication Point.new(@x*scalar, @y*scalar)
end
end

请注意,我们定义的*方法需要一个数值参数,而非Point对象,如果p是一个点,p*2是允许的;不过由于我们的实现方式,2*p是不能正常工作的。如果想要2*p与p*2返回同样的结果,可以定义一个coerce方法:
# If we try passing a Point to the * method of an Integer, it will call
# this method on the Point and then will try to multiply the elements of
# the array. Instead of doing type conversion, we switch the order of
# the operands, so that we invoke the * method defined above.
def coerce(other)
[self, other]
end

Array and Hash Access with [ ]

Ruby uses square brackets for array and hash access, and allows any class to define a
[] method and use these brackets itself. Let’s define a [] method for our class to allow
Point objects to be treated as read-only arrays of length 2, or as read-only hashes with
keys :x and :y:

    def [](index)
case index
when 0, -2 then @x
when 1,-1 then @y
when :x,"x" then @x
when :y,"y" then @y
else nil
end
end

Enumerating Coordinates枚举坐标

If a Point object can behave like an array with two elements, then perhaps we ought tobe able to iterate through those elements as we can with a true array. Here is a definition
of the each iterator for our Point class. Because a Point always has exactly two elements,
our iterator doesn’t have to loop; it can simply call yield twice:因为Point仅仅只有2个元素,没必要loop,仅仅调用yield两次即可。
# This iterator passes the X coordinate to the associated block, and then
# passes the Y coordinate, and then returns. It allows us to enumerate
# a point as if it were an array with two elements. This each method is
# required by the Enumerable module.
def each
yield @x
yield @y
end

With this iterator defined, we can write code like this:
p = Point.new(1,2)
p.each {|x| print x } # Prints "12"

更重要的是,一旦定义了each迭代器,我们就可以混入Enumerable模块的一些方法,这些方法都是基于each定义的,这样,通过加入下面的一行代码,他就会获得超过20个迭代器:
include Enumerable

如果加入了这行代码,我们就可以写出如下有趣的代码:
#is the point p at the origin
p.all? {|x| x==0} #true if the block is true for all elems

ruby面向对象class的更多相关文章

  1. Ruby面向对象

    Ruby面向对象 ​ Ruby是真正的面向对象语言,一切皆为对象,甚至基本数据类型都是对象 基本用法 class Box # 构造函数 def initialize(w,h) @with, @heig ...

  2. Ruby 面向对象知识详解

    Ruby 是纯面向对象的语言,Ruby 中的一切都是以对象的形式出现.Ruby 中的每个值都是一个对象,即使是最原始的东西:字符串.数字,甚至连 true 和 false 都是对象.类本身也是一个对象 ...

  3. 雷林鹏分享:Ruby 面向对象

    Ruby 面向对象 Ruby 是纯面向对象的语言,Ruby 中的一切都是以对象的形式出现.Ruby 中的每个值都是一个对象,即使是最原始的东西:字符串.数字,甚至连 true 和 false 都是对象 ...

  4. Python基础学习(一)之Python的概述与环境安装

    Python介绍 Python语言介绍 Python是一门高级的.面向对象的.解释性.脚本语言. 高级语言:贴近开发者,对应底层语言,底层语言贴近机器:java.C#.php .ruby 面向对象对应 ...

  5. 【Ruby】【高级编程】面向对象

    # [[面向对象]]#[实例变量]=begin实例变量是类属性,它们在使用类创建对象时就编程对象的属性.每个对象的属性是单独赋值的,和其他对象之间不共享.在类的内部,使用@运算符访问这些属性,在类的外 ...

  6. Ruby(面向对象程序设计的脚本语言)入门

    Ruby是一种为简单快捷的面向对象编程(面向对象程序设计)而创的脚本语言. 简单介绍 Ruby 是开源的,在Web上免费提供,但须要一个许可证. Ruby 是一种通用的.解释的编程语言. Ruby 是 ...

  7. ruby 基础知识(一)

    突然今天发现一大神的博客:http://www.cnblogs.com/jackluo/archive/2013/01/22/2871655.html    相信初学者会受益颇多 ruby  参考文档 ...

  8. Ruby之基本数据类型(三)

    前言 上一节我们介绍了常量以及变量的用法,这一节我们开始来介绍Ruby中的一些基本类型. 数值类型(Fixnum.Bignum.Float) Ruby的数值类型包括整数和浮点数.整数包括Fixnum和 ...

  9. Ruby之基础介绍(二)

    前言 上一篇我们简单介绍了下Ruby,这一节我们开始正式步入Ruby的世界,一探究竟. Ruby特点 (1)面向对象支持. (2)动态语言:我们可以修改已经定义过的类,也可以为现有类添加实例方法. ( ...

随机推荐

  1. Service层和DTO层的作用

    Service层主要提供的几个作用:1.将业务逻辑层进行封装,对外提供业务服务调用.2.通过外观模式,屏蔽业务逻辑内部方法.3.降低业务逻辑层与UI层的依赖,业务逻辑接口或实现的变化不会影像UI层.4 ...

  2. MyFramework框架搭建(一)DAL层

    一直以来有一个想法,搭建一个属于自己的框架,将自己学到的东西整合到框架里,不断的完善,让它随着我的成长而成长,下面介绍我第一阶段的总结:DAL层搭建 一.基础配置 1.我用的是Ibatis.net框架 ...

  3. 20151210jquery进阶 代码备份

    $(function () { /*$('form input[type=button]').click(function() { $.ajax({ type:'POST', //url:'http: ...

  4. 查看SQL server 2008 R2 的Service Package 版本号(同样适用于SQL Server 2005)

    在SQL Server 中新建一个查询(new Query),然后输入下面的SQL脚本,即可看到当前的数据库的Service Package (补丁包)的版本号 select serverproper ...

  5. .NET垃圾回收机制 转

    在.NET Framework中,内存中的资源(即所有二进制信息的集合)分为"托管资源"和"非托管资源".托管资源必须接受.NET Framework的CLR( ...

  6. 安装aptana插件报Error opening the editor. java.lang.NullPointerException

    Aptana的官方网站下载eclipse的插件:  http://update.aptana.com/update/studio/3.2/ ,可以在线安装也可以下载插件后再安装,我是以在线的形式安装的 ...

  7. [USACO1.1.4]坏掉的项链Broken Necklace

    P1203 [USACO1.1]坏掉的项链Broken Necklace 标签 搜索/枚举 USACO 难度 普及- 题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N&l ...

  8. c++primer复习(一)

    1 const对象默认为文件的局部变量(P50) a.cpp ; b.cpp extern int a;//undefined reference to "a" a.cpp ; b ...

  9. ubuntu 安装flash插件

    参考文献: http://wiki.debian.org.hk/w/Install_Flash_Player_with_APTapt-get install adobe-flashplugin

  10. js获取任意元素到页面的距离

    function getPos(obj){ var pos={left:0,top:0} while(obj){ pos.left+=obj.offsetLeft; pos.top+=obj.offs ...