Ruby: случай использования объекта - PullRequest
5 голосов
/ 13 июля 2011

Есть ли способ неявного вызова методов для объекта оператора case?IE:

class Foo

  def bar
    1
  end

  def baz
    ...
  end

end

Что я хотел бы сделать, это что-то вроде этого ...

foo = Foo.new
case foo
when .bar==1 then "something"
when .bar==2 then "something else"
when .baz==3 then "another thing"
end

... где операторы "когда" оценивают возвращаемое значениеметодов на объекте дела.Возможна ли такая структура?Я не смог выяснить синтаксис, если так ...

Ответы [ 4 ]

9 голосов
/ 13 июля 2011

FWIW, вам вообще не нужно передавать объект в оператор case в 1.8.7.

foo = Foo.new()
case
when foo.bar == this then that
when foo.baz == this then that
end

Я был удивлен как хег.

http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what-you-can-do-with-it/

7 голосов
/ 13 июля 2011

Что делает case .. when, так это вызывает метод === для ваших when значений, передавая объект foo в качестве аргумента методу ===.Итак, в этом коде:

case foo
when 1 then "something"
when 2 then "something else"
when 3 then "another thing"
end

Он будет пытаться 1 === foo, затем 2 === foo, затем 3 === foo, пока один из них не вернет истинное значение.

Один из способов сделатьcase .. when более мощный использует Procs в качестве значений when.Я не уверен насчет более ранних версий Ruby, но в 1.9 proc === x эквивалентен proc.call(x).Поэтому вы можете написать код, подобный следующему:

case foo
when Proc.new { foo.bar == 1 } then "something"
when Proc.new { foo.bar == 2 } then "something else"
when Proc.new { foo.baz == 3 } then "another thing"
end

Обратите внимание, что нам даже не нужно передавать foo в Procs, так как у нас уже есть доступ к нему.Я не думаю, что это очень хороший выбор структуры управления для этого примера, простейшая цепочка ifs имела бы больше смысла:

if foo.bar == 1
  "something"
elsif foo.bar == 2
  "something else"
elsif foo.baz == 3
  "another thing"
end
4 голосов
/ 13 июля 2011

Похоже, вы хотите изменить приемник по умолчанию.Это глупо, но вы могли бы сделать что-то вроде:

string = Foo.new.instance_eval do
  if bar==1 then "something"
  elsif bar==2 then "something else"
  elsif baz==3 then "another thing"
  end
end

Это большой, ужасный запах кода, хотя, если вы просто делаете это, потому что вы ленивы.Если вы делаете это, потому что вы создаете DSL, это нечто другое.

1 голос
/ 17 октября 2017

Для другого сценария, в котором вы хотите проверить истинное значение метода объекта

class Foo
  def approved?
    false
  end

  def pending?
    true
  end
end

foo = Foo.new
case foo
when :approved?.to_proc
  puts 'Green'
when :pending?.to_proc
  puts 'Amber'
else
  puts 'Grey'
end

# This will output:  "Amber"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...