在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
ruby对象是严格封装的:只能通过定义的方法访问其内部状态。方法使用的成员变量在对象外部不能直接访问,不过可以通过getter、setter等访问器方法(accessor),使他们看起来好像是直接访问的。 与对象状态的封装性相反,ruby中的类非常开放。每个ruby程序都可以为现有类添加方法,而且也可以为单个对象添加“单键方法(singleton method)”。 创建类Classes are created in Ruby with the class keyword: class关键字还创建了一个常量用于引用这个类,这个常量名与类名相同,因此所有类名必须以大写字母开头。(因为常量名必须以大写字母开头)。 class/module name must be CONSTANT 跟绝大多数ruby语句一样,class是一个表达式,class表达式得到值等于类定义体中最后一个表达式的值。一般而言,类的最后一个表达式都是一个用于定义方法的def语句,def语句的值总是等于nil。 实例化一个Point对象p = Point.new 常量Point代表了类对象,所有的类对象都有一个new方法。
初始化 通过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) 一旦定义了像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 Module有attr_reade和attr_accessor方法。因为所有的类都是模块(Class类是Module的子类),所以可以在任何类的实例中调用这些方法。每个方法接受任意数目的符号(用作属性名)作为参数,atrtr_reader为给定名字的实例变量创建同名的读者方法, 定义可变的类: class Point 定义不可变的类: Each of these methods can accept an attribute name or names as a string rather than attr_reader和attr_accessor方法可以为我们创建实例方法。这是元编程的一个例子。他展示了ruby的一个强大的特性。注意attr这些方法在类的定义内被调用,这使得他们仅在类定义时执行一次。在这里没有效率方面的问题:这样创建的读者和写者和硬编码出来的方法是一样快的。
Defining Operators定义操作符 We’d like the + operator to perform vector addition of two Point objects, the * operator 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方法:
Array and Hash Access with [ ]Ruby uses square brackets for array and hash access, and allows any class to define a 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
更重要的是,一旦定义了each迭代器,我们就可以混入Enumerable模块的一些方法,这些方法都是基于each定义的,这样,通过加入下面的一行代码,他就会获得超过20个迭代器: 如果加入了这行代码,我们就可以写出如下有趣的代码:
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论