ruby物件導向class

來源:互聯網
上載者:User

標籤:des   style   blog   color   get   使用   

 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            endend

這裡定義了一個執行個體方法,當一個執行個體方法被調用時,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.減號有一元的和二元的。[email protected]代表一元的。 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 [email protected] # Define unary minus to negate both coordinates        Point.new([email protected], -@y)    end    def *(scalar) # Define * to perform scalar multiplication        Point.new(@x*scalar, @y*scalar)    endend

請注意,我們定義的*方法需要一個數值參數,而非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

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.