zoukankan      html  css  js  c++  java
  • ruby面向对象class

     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

  • 相关阅读:
    python的函数修饰符(装饰器)
    hdu1175连连看(dfs+细节)
    hdu2553N皇后问题(dfs,八皇后)
    hdu1045Fire Net(经典dfs)
    hdu1050Moving Tables(贪心)
    hdu2037今年暑假不AC(贪心,活动安排问题)
    hdu1052Tian Ji -- The Horse Racing(贪心,细节多)
    hdu1009FatMouse' Trade(贪心)
    hdu1455Sticks(经典dfs+剪枝)
    hdu2509Be the Winner(反nim博弈)
  • 原文地址:https://www.cnblogs.com/youxin/p/3810924.html
Copyright © 2011-2022 走看看