Impementation Ruby <=> Combinator

Используйте: setButton(int whichButton, CharSequence text, DialogInterface.OnClickListener listener);

Для whichButton используйте одно из следующего:

DialogInterface.BUTTON_POSITIVE 
DialogInterface.BUTTON_NEGATIVE
DialogInterface.BUTTON_NEUTRAL 
6
задан Andrew Grimm 20 January 2011 в 12:03
поделиться

3 ответа

Вот рифф на вашу идею. Он не определяет никаких дополнительных констант, позволяет использовать любую комбинацию переменных экземпляра и методов для сравнения двух объектов, имеет ранний выход при неравенстве и включает все методы, определенные Comparable.

class Object
    def self.compare_by(*symbols)
        include Comparable
        dispatchers = symbols.map do |symbol|
          if symbol.to_s =~ /^@/
            lambda { |o| o.instance_variable_get(symbol) }
          else
            lambda { |o| o.__send__(symbol) }
          end
        end
        define_method('<=>') do |other|
          dispatchers.inject(0) do |_,dispatcher|
            comp = dispatcher[self] <=> dispatcher[other]
            break comp if comp != 0
            comp
          end
        end
    end
end

class T
    def initialize(name,f1,f2,f3)
      @name,@f1, @f2, @f3 = name,f1, f2, f3;
    end

    def f1
      puts "checking #@name's f1"
      @f1
    end
    def f3
      puts "checking #@name's f3"
      @f3
    end

    compare_by :f1, :@f2, :f3
end

w = T.new('x',1,1,2)
x = T.new('x',1,2,3)
y = T.new('y',2,3,4)
z = T.new('z',2,3,5)

p w < x   #=> checking x's f1
          #   checking x's f1
          #   true
p x == y  #=> checking x's f1
          #   checking y's f1
          #   false
p y <= z  #=> checking y's f1
          #   checking z's f1
          #   checking y's f3
          #   checking z's f3
          #   true

Если хотите, вы можете может вставить дополнительную проверку ошибок, чтобы убедиться, что значения, используемые для сравнения, фактически отвечают на <=> (с использованием response_to? '<=>' ) и пытаются давать более четкие сообщения об ошибках в тех случаях, когда они этого не делают.

7
ответ дан 8 December 2019 в 13:48
поделиться

Что ж, вот небольшой совет по расширению Object , чтобы это произошло, что кажется достаточно приятным способом.

class Object

    def self.spaceship_uses(*methods)
        self.const_set(:SPACESHIP_USES, methods)
    end

    def <=>(o)
        raise(NoMethodError, "undefined method `<=>' for #{self.inspect}") \
            unless self.class.const_defined?(:SPACESHIP_USES)
        self.class.const_get(:SPACESHIP_USES).each { |sym|
            self.send(sym) < o.send(sym) && (return -1)
            self.send(sym) > o.send(sym) && (return  1)
        }
        return 0
    end

end

class T

    def initialize(f1, f2) @f1, @f2 = f1, f2; end

    attr_reader    :f1, :f2
    spaceship_uses :f1, :f2

end

Это, конечно, не так. решите любые проблемы с типизацией, чтобы убедиться, что < и > правильно реализованы для объектов, возвращаемых методами в SPACESHIP_USES . Но с другой стороны, для Ruby это нормально, не так ли?

Короткие комментарии могут прокомментировать это, но мне было бы интересно увидеть подробное обсуждение и расширения в других ответах.

0
ответ дан 8 December 2019 в 13:48
поделиться

Вот что я делаю, чтобы сделать настраиваемые правила сортировки более управляемыми: для всех моих классов, которые мне когда-либо нужно сортировать, я определяю методы "to_sort", которые возвращают массивы, а затем переопределяю <=> для использования to_sort:

class Whatever
  def to_sort
    [@mainkey,@subkey,@subsubkey]
  end

  def <=>(o)
    self.to_sort <=> o.to_sort
  end
end

Таким образом, сортировка любого массива Whatevers (включая гетерогенные массивы Whatevers, Whateverothers и Whathaveyours, все из которых реализуют функции to_sort, зависящие от типа и то же самое переопределение <=>) просто переходит на внутреннюю сортировку массива массивов.

8
ответ дан 8 December 2019 в 13:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: