• Ruby和面向对象技术


    Ruby和许多极为流行的编程语言都是面向对象的。多数的面向对象编程语言,每个对象都是一个样例或者既定类的实例以及独立对象的行为。

    一、创建一个通用对象

    创建一个通用对象

    obj = Object.new
    
    • 1

    定义通用对象的行为

    def obj.talk 
        puts "I am an object"
        puts "(Do you object?)"
    end
    
    • 1
    • 2
    • 3
    • 4

    定义带参数的方法

    def obj.c2f(c)
        c * 9.0 / 5 + 32
    end
    
    • 1
    • 2
    • 3

    任何方法的返回值与方法执行中最后一个表达式的计算值相等
    Ruby提供了一个关键字明确地定义了返回值:return,这个关键字地使用通常是可选的,但是多数程序员都喜欢用它,因为它使隐式的返回值表达式变得显而易见。

    def obj.c2f(c)
        return c * 9.0 / 5 + 32
    end
    
    • 1
    • 2
    • 3

    假如需要返回多个值则必须使用它,这些值会自动被包装为一个数组。

    二、制作一个对象

    一张入场券是一个常见的对象,且有一组众人熟知的属性和行为。这里将从一个较高的视角来看待一个如入场券般的Ruby对象能做什么以及该对象对自身的理解。
    创建一个ticket.rb

    ticket =  Object.new
    
    def ticket.date
        "01/02/03"
    end
    def ticket.venue
        "Town Hall"
    end
    def ticket.event
        "Author's reading"
    end
    def ticket.performer
        "Mark Twain"
    end
    
    def ticket.seat
        "Second Balcony, row J, seat 12"
    end
    
    def ticket.price
        5.50
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这个马克吐温的入场券是一个简单的例子,但是它包含了一些Ruby编程的重要流程和原则。这个最重要的经验就是:程序完成任何有用事情的信息都必须存储于对象之中。ticket对象拥有这些信息,通过方法的调用可以请求ticket对象返回信息

    查询对象

    print "This ticket is for: "
    print ticket.event + ", at "
    print ticket.venue + ", on "
    puts ticket.date + "."
    print "The performer is "
    puts ticket.performer + "."
    print "The seat is "
    print ticket.seat + ", "
    print "and it costs $"
    puts "%.2f." % ticket.price
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    通过字符串插值缩短查询代码:

    puts "This ticket is for: #{ticket.event}, at #{ticket.venue}" + 
        "The performer is: #{ticket.performer}." + 
        "The seat is: #{ticket.seat}, " + 
        "The it costs #{"%.2f." % ticket.price}"
    
    • 1
    • 2
    • 3
    • 4

    无论在插值运算符中的内容是什么,他都能被分步求值,求值的结果会被插入字符串中。

    用方法表达布尔状态

    def ticket.avai_status
        "sold"
    end
    def ticket.avai?
        false
    end
    
    if ticket.avai?
        puts "You are in luck!"
    else
        puts "Sorry--that seat has been sold."
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意方法avai?以问号结尾

    三、对象的原生行为

    就算是新创建的对象也不会是一块白板。只要对象创建并存在,它就能响应一组消息。
    输入以下命令可以查看原生方法的列表:

    Object.new.methods.sort
    
    • 1

    在这里插入图片描述
    这些原生方法中的一小部分是非常普遍和非常有用的。

    1、用object_id表示唯一标识对象

    在Ruby中,每个对象都有一个和它唯一关联的ID编号。可以通过请求一个对象的object_id获得一个对象的ID,使用如下类似的代码。

    obj = Object.new
    puts "The id of obj is #{obj.object_id}."
    str = "Strings are objects too, and this is a string!"
    puts "The id of the string object str is #{str.object_id}."
    puts "And the id of the integer 100 is #{100.object_id}"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行这段代码可以看到

    The id of obj is 60.
    The id of the string object str is 80.
    And the id of the integer 100 is 201
    
    • 1
    • 2
    • 3

    在尝试确定两个对象是否相等的时候,每个对象都拥有一个唯一的ID编号是很有用的,可以通过判断object_id是否相等而判断两个对象是否相等。

    a = Object.new
    b = a
    puts "a's id is #{a.object_id} and b's id is #{b.object_id}"
    
    • 1
    • 2
    • 3

    运行之后可以看到a和b的对象id是相同的。

    2、用respond_to?方法查询对象的能力

    Ruby对象响应消息。在程序运行期间的不同事件点,依赖于对象和为对象定义的各种方法,一个对象可能会响应指定的消息,也可能不会。所以可以使用respond_to?方法判断一个对象是否有某种方法。

    if obj.respond_to?("talk")
        obj.talk
    else 
        puts "Sorry, the object doesn't understand the 'talk' message"
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5

    该方法时自省或者反射的一个例子,这两个词指的是可以在程序运行期间进行状态检测。Ruby提供了许多用于自省机制的工具。使用methods方法测试对象,是另一种自省和反射的技术。

    3、用send方法发送信息给对象

    如果希望从键盘输入合适的查询词组(venue、performer等),就能从ticket对象中得到信息,则需要把如下代码添加到已有的程序中:

    print "Information desired: "
    request = gets.chomp
    
    • 1
    • 2

    该行代码可以从键盘中获取一行输入。这样可以使用双等号比较符测试两个不同的输入值,它会基于对象自身的内容对字符串进行比较,然后调用与值匹配的方法。

    if request == "venue"
        puts ticket.venue
    elsif request == "performer"
        puts ticket.performer
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5

    尽管如此,还是不得不继续编写整个入场券的属性列表,但那变得有些冗余了。
    这里还有一个可选的方案:给ticket对象直接发送对应的词语。按如下方式替换前面例子里的代码:

    if  ticket.respond_to?(request)
        puts ticket.send(request)
    else 
        puts "No such information available"
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这个版本中使用了send方法作为ticket对象获得消息的通用入口。这样可以避免整个可能的请求清单,并由处理ticket对象的消息执行该消息,以取代检查ticket对象所具有的能力。
    还可以使用__send__或者public_send代替send,__send__方法比普通send更安全,而public_send不能访问私有方法。

    四、方法参数

    在编写方法的时候允许传递任意数量的参数,在单独的方法参数名称前使用一个*即可:

    def obj.multi_args(*x)
        puts "I can take zero or more arguments!"
    end
    
    • 1
    • 2
    • 3

    符号*x表示在调用方法的时候,可以提供任意数量的参数。变量x被分配一个对应任意参数的数组。可以在稍后使用数组每次测试其中的一个。
    一般情况下,参数都是变量的引用,如果不想变量发生变化,可以传入s.dup复制了一个对象。

    def change_string(s)
        s.replace("New String!")
    end
    s = "Original String"
    change_string(s)
    change_string(s.dup)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    还可以冻结一个变量,冻结后不能再对这个变量发生改变

    s.freeze
    
    • 1
  • 相关阅读:
    MySQL8.0-分组函数ROLLUP的基本用法(GROUPING)
    mac读写硬盘的软件Tuxera NTFS2023免费版下载
    [附源码]计算机毕业设计springboot面向高校活动聚App
    HTL6033是一款专用于3串锂电池或聚合物电池的保护芯片
    Python configparser模块
    B_QuRT_User_Guide(34)
    HOW TO EASILY CREATE BARPLOTS WITH ERROR BARS IN R
    AcWing 831. KMP字符串
    20.1 OpenSSL 字符BASE64压缩算法
    IDEA闪退解决方案记录
  • 原文地址:https://blog.csdn.net/weixin_44014982/article/details/133852690