如何在 Ruby 中使用模块扩展浮点和数组类

Posted

技术标签:

【中文标题】如何在 Ruby 中使用模块扩展浮点和数组类【英文标题】:How to extend Float and Array classes using modules in Ruby 【发布时间】:2021-01-16 11:08:34 【问题描述】:

在为模块中的 Float 和 Array 类定义新方法时,我发现 方法不被承认为方法,尽管该模块被包含在内。我只是成为 熟悉 Ruby 中模块的使用,因此我将不胜感激。代码如下:


#! /usr/bin/env ruby

module NewMath

    include Math        

puts("Hello from NewMath")

class Array

    def mean
        raise Exception, "#self should be a uniform array of numbers" if     
           !hasElementsOfUniformType?( self) || !self.first.is_a?(Numeric)
        sum = inject(&:+)
        
        return (self.first.is_a?(Integer)) ? sum / size : sum / size.to_f
    end
    
    def standardDeviation
        raise Exception, "#self should be a uniform array of numbers" if  \
              !hasElementsOfUniformType?( self) || !self.first.is_a?(Numeric)
        raise ArgumentError, "#self should be an array of more than 1 numbers" if \
              self.size < 2     

        mn = self.mean          
        sumOfDeviationSqr = self.map  |x| x.to_f - mn.to_f  \
           .map  |deviation| deviation * deviation .reduce(:+) / (size - 1).to_f
        
        return  Math.sqrt(sumOfDeviationSqr)    
    end
end

class Integer
    def notToExceed( limit)
        return (self > limit) ? limit : self
    end
end 

class Float
    def constrainAndFormat(low:, high:, decimalPlaces:)
    raise Exception, "low: #low should be a Float" if !low.is_a?(Float)
    raise Exception, "high: #high should be a Float value > #lo" \
         if !high.is_a?(Float) || high < low
    raise Exception, "decimalPlaces: #decimalPlaces should be a positive integer" \
         if (decimalPlaces < 1)
        item = (self > high) ? high : (self < low) ? low : self
        
        factor = 1.upto(decimalPlaces).map  |i| 10.to_f .reduce(:*)                       
        truncate = (item * factor).to_i.to_f
        return truncate / factor            
    end
end
end

include NewMath


print("\n Array's public instance methods: #Array.public_instance_methods")
print
print("\n Array's included modules: #Array.included_modules")
print
list = []
100.times.each do 
    list << rand(1..100)
end
print("\n list = #list\n")
print("\n s.d. = #list.standardDeviation\n")

a = list.mean
print("\n mean = #a\n")

print("\n Float's public instance methods: #Float.public_instance_methods")
l = 1.0 /3.0
print("\n l = #l , #l.constrainAndFormat(low: 0.0, high:2.0, decimalPlaces:4)")


************************* end of code *******************************************

Mean, standardDeviation, and constrainAndFormat are undefined.  Array's list of public  
instance methods excludes standardDeviation.

Array 的公共实例方法:[:to_h, :include?, :at, :fetch, :last, :union, :difference, :push, :append, :pop, :shift, :unshift, :each_index, : join, :rotate, :rotate!, :sort!, :sort_by!, :collect!, :map!, :select!, :filter!, :keep_if, :values_at, :delete_at, :delete_if, :reject!, :转置、:fill、:assoc、:rassoc、:uniq!、:compact、:compact!、:flatten、:flatten!、:shuffle!、:shuffle、:*、:+、:permutation、:&、:repeated_permutation , :combination, :sample, :repeated_combination, :product, :bsearch, :-, :sort, :bsearch_index, :count, :find_index, :select, :filter, :reject, :collect, :map, :first, : all?, :any?, :one?, :none?, :reverse_each, :zip, :take, :take_while, :drop, :drop_while, :cycle, :sum, :uniq, :|, :insert, :, :id, :instance_exec, :!=, :instance_eval, :发送] Array 包含的模块:[Enumerable, NewMath, Math, Kernel] 列表 = [90, 61, 39, 63, 17, 39, 26, 9, 91, 69, 67, 39, 33, 13, 63, 68, 100, 58, 25, 3, 37, 28, 56, 43 , 100, 43, 3, 3, 25, 97, 56, 20, 86, 25, 21, 60, 8, 20, 87, 32, 1, 97, 52, 51, 83, 86, 57, 55, 91 , 16, 49, 83, 46, 82, 58, 56, 40, 22, 8, 60, 91, 5, 50, 11, 57, 27, 53, 39, 83, 12, 90, 92, 61, 83 , 31, 87, 63, 97, 76, 66, 58, 24, 8, 82, 17, 44, 76, 43, 71, 29, 95, 34, 22, 54, 90, 5, 11, 98, 26 , 79] 回溯(最近一次通话最后): ./newTesting.rb:63:in &lt;main&gt;': undefined method standardDeviation' for #Array:0x00007fdd9514c768 (NoMethodError)

【问题讨论】:

【参考方案1】:

您已经定义了三个类,NewMath::ArrayNewMath::IntegerNewMath::Float

然后,您已将NewMath 模块包含到main(***范围)中。 include 做了一些事情,但“合并具有相同名称的类”不是其中之一。它不会“合并”ArrayNewMath::Array

你想要做的可能是:

module NewMath
  module Array
    def foo
      puts "foo"
    end
  end
end

Array.include(NewMath::Array)

[].foo # prints "foo"

很高兴你尝试这样做 b/c 这保留了所有者:

pry(main)> [].method(:foo).owner
=> NewMath::Array

这使得代码很容易找到。这与直接打开类相反:

# this could be in any file, anywhere
class Array
  def bar
    puts "bar"
  end
end

[].method(:bar).owner # => Array  (gives you no indication where it came from)

【讨论】:

以上是关于如何在 Ruby 中使用模块扩展浮点和数组类的主要内容,如果未能解决你的问题,请参考以下文章

java 父类如何在运行期动态获取子类类名

随机森林分类如何在幕后工作?

serversocket 类如何在同一个端口上服务多个客户端连接?

idea java中Jformdesigner自动生成的类如何在public static void main(String[] args)}中引用

方法如何在 Ruby 中使用哈希参数?

Ruby mixins:扩展和包含