代码之家  ›  专栏  ›  技术社区  ›  ab217

在Ruby中,是否有方法重载初始化构造函数?

  •  64
  • ab217  · 技术社区  · 14 年前

    在Java中,可以重载构造函数:

    public Person(String name) {
      this.name = name;
    }
    public Person(String firstName, String lastName) {
       this(firstName + " " + lastName);
    }
    

    Ruby中有没有一种方法可以达到同样的结果:两个构造函数采用不同的参数?

    7 回复  |  直到 14 年前
        1
  •  74
  •   Steve Weet    14 年前

    答案是肯定的和否定的。

    您可以使用多种机制获得与其他语言相同的结果,包括:-

    • 变量参数列表(splat运算符)

    语言的实际语法不允许您定义两次方法,即使参数不同。

    考虑到上面的三个选项,可以通过下面的示例实现这些选项

    # As written by @Justice
    class Person
      def initialize(name, lastName = nil)
        name = name + " " + lastName unless lastName.nil?
        @name = name
      end
    end
    
    
    class Person
      def initialize(args)
        name = args["name"] + " " + args["lastName"] unless args["lastName"].nil?
        @name = name
      end
    end
    
    class Person
      def initialize(*args)
        #Process args (An array)
      end
    end
    

    您将经常在Ruby代码中遇到第二种机制,特别是在Rails中,因为它提供了两个世界中最好的一面,并且允许一些语法糖生成漂亮的代码,特别是不必将传递的散列括在大括号中。

    这个 wikibooks link 提供更多的阅读

        2
  •  27
  •   Andrew Grimm atk    14 年前

    class Person
      def self.new_using_both_names(first_name, last_name)
        self.new([first_name, last_name].join(" "))
      end
    
      def self.new_using_single_name(single_name)
        self.new(single_name)
      end
    
      def initialize(name)
        @name = name
      end
    end
    

    但我不知道这是不是最好的方法。

        3
  •  4
  •   yfeldblum    14 年前
    class Person
      def initialize(name, lastName = nil)
        name = name + " " + lastName unless lastName.nil?
        @name = name
      end
    end
    
        4
  •  3
  •   hexinpeter    9 年前
    class StatementItem
      attr_reader :category, :id, :time, :amount
    
      def initialize(item)
        case item
        when Order
          initialize_with_order(item)
        when Transaction
          initialize_with_transaction(item)
        end
      end
    
      def valid?
        !(@category && @id && @time && @amount).nil?
      end
    
      private
        def initialize_with_order(order)
          return nil if order.status != 'completed'
          @category = 'order'
          @id = order.id
          @time = order.updated_at
          @amount = order.price
        end
    
        def initialize_with_transaction(transaction)
          @category = transaction.category
          @id = transaction.id
          @time = transaction.updated_at
          @amount = transaction.amount
        end
    
    end
    
        5
  •  1
  •   aaronkelton    5 年前

    你可以用 ** (双管) || initialize 方法达到同样的效果。

    class Person
      def initialize(**options)
        @name = options[:name] || options[:first_name] << ' ' << options[:last_name]
      end
    end
    
    james = Person.new(name: 'James')
    #=> #<Person @name="James">
    
    jill_masterson = Person.new(first_name: 'Jill', last_name: 'Masterson')
    #=> #<Person @name="Jill Masterson">
    

    但是,如果 Person 创建时没有 first_name ,然后追加 << 操作将失败 NoMethodError: undefined method '<<' for nil:NilClass . 这是一个重构的 初始化 strip 删除空白如果 选项被排除在外)。

    class Person
      def initialize(**options)
        @name = options[:name] || [ options[:first_name] , options[:last_name] ].join(' ').strip
      end
    end
    
    goldfinger = Person.new(last_name: 'Goldfinger')
    #=> #<Person @name="Goldfinger">
    
    oddjob = Person.new(first_name: 'Oddjob')
    #=> #<Person @name="Oddjob">
    

    实际上,这种方法处理调用 Person.new @name 设置为空字符串:

    nameless = Person.new
    #=> <#Person @name="">
    
    middle_malcom = Person.new(middle_name: 'Malcom')
    #=> <#Person @name="">
    
        6
  •  0
  •   snovity    8 年前

    你可以用 konstructor 用Ruby声明多个构造函数并模拟重载的gem:

    class Person
      def initialize(name)
        @name = name
      end
    
      konstructor
      def from_two_names(first_name, last_name)
        @name = first_name + ' ' + last_name
      end
    end
    
    Person.new('John Doe')
    Person.from_two_names('John', 'Doe')
    
        7
  •  0
  •   Oshan Wisumperuma    5 年前

    结帐 functional-ruby 以长生不老药为灵感的宝石 pattern matching 特征。

       class Person
         include Functional::PatternMatching
    
         defn(:initialize, String) { |name| 
           @name = name 
         }
    
         defn(:initialize, String, String) {|first_name, last_name| 
          @name = first_name + ' ' + last_name
         }
       end