Что означают две вертикальные линии и super.select в блоке кода? - PullRequest
0 голосов
/ 26 января 2019

Что на самом деле означает следующее?

def method
  super.select { |a| a.meets_condition? || true }
end

Я особенно борюсь с || в данном контексте. Трудно найти ответы на этот вопрос с помощью поисковой системы.

Что делает super.select?

Что делает метод, если часть "|| true" удалена?

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Это довольно странный кусок кода, но это то, что он делает:

вы определяете метод с именем method

специальный метод super означает вызов метода с тем же именем в родительском (супер) классе.

вы берете результат super, который должен быть «перечисляемым» объектом, таким как массив или хэш, и вызываете select для этого объекта

select проходит через перечислимый объект (предположим, что это массив) и вызывает блок с каждым элементом. Обычно он используется для фильтрации (или выбора) некоторых объектов из массива. Каждый раз, когда блок вызывается, он возвращает истинное или ложное значение. Если правда, то этот элемент сохраняется в результирующем массиве. Если фальсифицировано, его выбрасывают.

Хорошо, так что каждый элемент этого массива будет выполнять это на нем:

a.meets_condition? || true

, что странно, потому что это вызовет meets_condition? для элемента массива, и если он возвращает истинное значение, то этот элемент (a) сохраняется в массиве.

но что, если a.meets_condition? является ложью?

Затем мы переходим к следующей части or (двойные трубы) и делаем это.

Что возвращает true.

Таким образом, в основном это выражение будет возвращать копию массива, который вы передали.

Давайте превратим пример в настоящий рабочий пример:

class RandomDigit
  # gives you a object containing a random digit between 0 and 9
  def initialize
    @n = rand(10)
  end
  def meets_condition?  # returns true if @n is even 
    @n % 2 == 0 
  end
end

class TheParentClass
  def method
    # returns array of 4 random digits (between 0 and 9)
    [RandomDigit.new, RandomDigit.new, RandomDigit.new, RandomDigit.new]
  end
end

class TheChildClass < TheParentClass
  def method
    # super means we are calling TheParentClass.method
    # select will try each element of the the array 
    # and builds a new array, with elements that returned true
    # but the trouble is || true means its always going to return true
    super.select { |a| a.meets_condition? || true }
  end
end

puts TheChildClass.new.method # -> returns 4 random digits

Вы можете нажать на эту ссылку, чтобы запустить код и увидеть, как он работает

http://opalrb.com/try/?code:class%20RandomDigit%0A%20%20def%20initialize%0A%20%20%20%20%40n%20%3D%20rand(10)%0A%20%20end%0A%20%20def%20meets_condition%3F%0A%20%20%20%20%40n%20%25%202%20%3D%3D%200%20%23%20returns%20true%20if%20%40n%20is%20even%0A%20%20end%0Aend%0A%0Aclass%20TheParentClass%0A%20%20def%20method%0A%20%20%20%20%23%20returns%204%20random%20digits%20(between%200%20and%209)%0A%20%20%20%20%5BRandomDigit.new%2C%20RandomDigit.new%2C%20RandomDigit.new%2C%20RandomDigit.new%5D%0A%20%20end%0Aend%0A%0Aclass%20TheChildClass%20%3C%20TheParentClass%0A%20%20def%20method%0A%20%20%20%20super.select%20%7B%20%7Ca%7C%20a.meets_condition%3F%20%7C%7C%20true%20%7D%0A%20%20end%0Aend%0A%0Aputs%20TheChildClass.new.method

Просто чтобы прояснить, единственная вещь, которая на самом деле не имеет здесь смысла, - это || true часть.

В противном случае вы определяете новый класс и немного изменяете поведение method, чтобы оно работало подобно исходному method, но отфильтровывало элементы.

Обычно вы можете увидеть что-то вроде a.question_1? || a.question_2?

что было бы попробовать вопрос_1? и если он возвращает true, то все готово.

если он не возвращает true, тогда попробуйте вопрос_2.

Это потому, что || - это поток операций управления ... вторая часть НЕ выполняется, если первая часть уже выполнена.

&& является противоположным, поскольку вторая часть не выполняется, если только первая часть не истинна.

0 голосов
/ 26 января 2019

Этот метод вызывает метод с тем же именем из родительского класса, а затем вызывает #select метод для возвращаемого значения. Пример:

class Class1
  def method
    puts 'OK'
    'NOT OK'
  end
end

class Class2 < Class1
  def method
    puts super.downcase
  end
end

Class2.new.method

Это напечатает:

OK
не в порядке


Метод Class2#method вызывает метод Class1#method (Class1#method печатает «ОК» и возвращает «НЕ ОК»), а затем возвращается нижний регистр Строка «НЕ ОК» до ' не в порядке ' и печатает его.


В вашем примере две вертикальные строки в блоке для #select означают 'логическое ИЛИ' и целое выражение a.meets_condition? || true могут использоваться по двум причинам:

  1. Это может быть оценено как результат вызова a.meets_condition? (если этот результат не true или nil) или true в противном случае.
  2. Может выдать исключение, если a.meets_condition? выдает исключение. Это исключение можно перехватить и обработать на верхнем уровне стека вызовов.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...