gpt4 book ai didi

ruby - Ruby 中的静态 block

转载 作者:数据小太阳 更新时间:2023-10-29 07:20:34 25 4
gpt4 key购买 nike

我已经成为 Java 程序员有一段时间了,我正在尝试切换到 ruby​​ 一段时间。我只是想用 ruby​​ 开发一个小测试程序,我的意图是这样的。

  • 我想在 ruby​​ 中创建一个对象的简单链表类型;其中类中的实例变量指向相同类型的另一个实例。
  • 我想填充和链接所有节点;在调用构造函数之前并且只调用一次。我们通常在 Java Static 块中做的事情。
  • Initialize 方法是 ruby​​ 中的构造函数签名。他们周围有什么规则吗?就像在 Java 中一样,如果构造函数不是第一行(或在调用类代码之后?),则不能从构造函数调用另一个构造函数

  • 谢谢您的帮助。
    -普里扬克

    最佳答案

    I want to create a simple linked list type of an object in ruby; where an instance variable in class points to another instance of same type.



    只是一个简短的说明:单词类型在 Ruby 中是一个非常危险的词,尤其是如果您来自 Java。由于一个历史性的事故,这个词在动态类型和静态类型中都使用,表示两个只是表面相关但非常不同的东西。

    在动态类型中,类型是附加到值(而不是引用)的标签。

    此外,在 Ruby 中,类型的概念比在 Java 中广泛得多。在 Java 程序员的心目中,“类型”与“类”的意思相同(尽管事实并非如此,因为接口(interface)和原语也是类型)。在 Ruby 中,“类型”的意思是“我可以用它做什么”。

    示例:在 Java 中,当我说某个东西是 String 类型时,我的意思是它是 String 的直接实例。类(class)。在 Ruby 中,当我说某些东西是 String 类型时,我的意思是它要么是
  • String 的直接实例类(class)或
  • String 的子类的实例类(class)或
  • 响应 #to_str 的对象方法或
  • 行为与字符串无法区分的对象。

  • I want to populate and link all nodes; before the constructor is called and only once. Something that we'd usually do in Java Static block.



    在 Ruby 中,一切都是可执行的。特别是,没有“类声明”这样的东西:类体只是可执行代码,就像任何其他代码一样。如果您的类主体中有一个方法定义列表,那么那些不是由编译器读取然后转换为类对象的声明。这些是由评估器一一执行的表达式。

    因此,您可以将任何您喜欢的代码放入类体中,并且在创建类时将评估该代码。在类主体的上下文中, self绑定(bind)到类(请记住,类和其他任何对象一样只是对象)。

    Initialize method is a constructor signature in ruby. Are there any rules around them? Like in Java you cannot call another constructor from a constructor if its not the first line (or after calling the class code?)



    Ruby 没有构造函数。构造函数只是工厂方法(有愚蠢的限制);如果您可以使用(更强大的)工厂方法来代替,则没有理由将它们放在精心设计的语言中。

    Ruby 中的对象构造是这样工作的:对象构造分为两个阶段,分配和初始化。分配由名为 allocate 的公共(public)类方法完成。 ,它被定义为类 Class 的实例方法并且通常永远不会被覆盖。它只是为对象分配内存空间并设置一些指针,但是,此时对象并不是真正可用的。

    这就是初始化器的用武之地:它是一个名为 initialize 的实例方法。 ,它设置对象的内部状态并将其带入一致的、完全定义的状态,可供其他对象使用。

    因此,为了完全创建一个新对象,您需要做的是:
    x = X.allocate
    x.initialize

    [注意:Objective-C 程序员可能会认识到这一点。]

    但是因为太容易忘记打电话 initialize作为一般规则,对象在构造后应该完全有效,有一个名为 Class#new 的便利工厂方法。 ,它可以为您完成所有工作,看起来像这样:
    class Class
    def new(*args, &block)
    obj = alloc
    obj.initialize(*args, &block)

    return obj
    end
    end

    [注:实际上, initialize是私有(private)的,所以必须使用反射来规避这样的访问限制: obj.send(:initialize, *args, &block) ]

    顺便说一下,这就是为什么要构造一个您调用公共(public)类方法的对象 Foo.new但是你实现了一个私有(private)实例方法 Foo#initialize ,这似乎绊倒了很多新人。

    回答您的问题:由于初始化方法与其他任何方法一样,因此您在初始化方法中可以做什么绝对没有限制,特别是您可以调用 super无论何时,何地,无论何时,以及您想要的频率。

    顺便说一句:自从 initializenew只是普通的方法,没有理由需要调用它们 initializenew .这只是一个约定,尽管它非常强大,因为它体现在核心库中。在您的情况下,您想编写一个集合类,并且集合类提供一种名为 [] 的替代工厂方法是很常见的。 ,以便我可以拨打 List[1, 2, 3]而不是 List.new(1, 2, 3) .

    顺便提一下:使用普通方法进行对象构造的一个明显优势是您可以构造匿名类的实例。这在 Java 中是不可能的,绝对没有任何合理的理由。它不起作用的唯一原因是构造函数与类同名,而匿名类没有名称,因此不能有构造函数。

    虽然我不太确定为什么在创建对象之前需要运行任何东西。除非我遗漏了一些东西,否则列表基本上不应该是
    class List
    def initialize(head=nil, *tail)
    @head = head
    @tail = List.new(*tail) unless tail.empty?
    end
    end

    对于 Lisp 风格的缺点列表或
    class List
    def initialize(*elems)
    elems.map! {|el| Element.new(el)}
    elems.zip(elems.drop(1)) {|prv, nxt| prv.instance_variable_set(:@next, nxt)}
    @head = elems.first
    end

    class Element
    def initialize(this)
    @this = this
    end
    end
    end

    一个简单的链表?

    关于ruby - Ruby 中的静态 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1859747/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com