Вы также можете получить эту проблему, если у вас есть сценарий кода вашего контейнера приложения Swift 2.3, и вы создаете новое расширение в Xcode 8.
Чтобы решить вышеупомянутый сценарий ...
Примечание: Весь код должен быть в одной и той же быстрой (совместимой) версии для компиляции без сбоев.
При этом, одним из способов решения этой проблемы является , придерживаясь Swift 2.3 , а затем устанавливая для вашей цели расширения Использовать Legacy Swift Language Version значение «Да» .
Вы можете найти эту опцию, когда Xcode 8 открыт, следующим образом:
Примечание: Возможно, вам придется исправить переопределенный код в шаблонах расширений, поскольку они изначально были в Swift 3.
Как сказано в документации, class_eval
оценивает строку или блок в контексте модуля или класса. Таким образом, следующие фрагменты кода эквивалентны:
class String
def lowercase
self.downcase
end
end
String.class_eval do
def lowercase
self.downcase
end
end
В каждом случае класс String был повторно открыт и определен новый метод. Этот метод доступен для всех экземпляров класса, поэтому:
"This Is Confusing".lowercase
=> "this is confusing"
"The Smiths on Charlie's Bus".lowercase
=> "the smiths on charlie's bus"
class_eval
имеет ряд преимуществ перед простым повторным открытием класса. Во-первых, вы можете легко вызвать его для переменной, и вам будет ясно, каковы ваши намерения. Еще одно преимущество состоит в том, что он не сработает, если класс не существует. Таким образом, приведенный ниже пример завершится ошибкой, поскольку Массив
написан неправильно. Если бы класс был просто повторно открыт, он был бы успешным (и был бы определен новый неправильный класс Aray
):
Aray.class_eval do
include MyAmazingArrayExtensions
end
Наконец, class_eval
может принимать строку, что может быть полезно, если вы делаете что-то более гнусное ...
instance_eval
, с другой стороны, оценивает код для одного экземпляра объекта:
confusing = "This Is Confusing"
confusing.instance_eval do
def lowercase
self.downcase
end
end
confusing.lowercase
=> "this is confusing"
"The Smiths on Charlie's Bus".lowercase
NoMethodError: undefined method ‘lowercase’ for "The Smiths on Charlie's Bus":String
Итак, с instance_eval
метод определен только для этого единственного экземпляра строки.
Итак, почему instance_eval
в Class
определяет методы класса?
Так же, как «Это сбивает с толку»
и «Смиты в автобусе Чарли»
являются экземплярами String
, Array
, String
, Hash
и все другие классы сами являются экземплярами Class
. Вы можете проверить это, позвонив им по номеру #class
:
"This Is Confusing".class
=> String
String.class
=> Class
Итак, когда мы вызываем instance_eval
, он делает то же самое с классом, что и с любым другим объектом. Если мы используем instance_eval
для определения метода в классе, он будет определять метод только для этого экземпляра класса, а не для всех классов. Мы могли бы назвать этот метод методом класса, но это просто метод экземпляра для этого конкретного класса.
instance_eval эффективно создает одноэлементный метод для рассматриваемого экземпляра объекта. class_eval создаст обычный метод в контексте данного класса, доступный для всех объектов этого класса.
Вот ссылка на одноэлементные методы и одноэлементный шаблон (не специфичный для Ruby )
Я думаю, вы ошиблись. class_eval добавляет метод в класс, поэтому все экземпляры будут иметь метод. instance_eval добавит метод только к одному конкретному объекту.
foo = Foo.new
foo.instance_eval do
def instance_bar
"instance_bar"
end
end
foo.instance_bar #=> "instance_bar"
baz = Foo.new
baz.instance_bar #=> undefined method
Другой ответ правильный, но позвольте мне немного углубиться.
Ruby имеет несколько различных видов области видимости; шесть согласно википедии , хотя подробная формальная документация, похоже, отсутствует. В этом вопросе используются следующие области: неудивительно, что экземпляр и класс .
Текущая область действия экземпляра определяется значением self
. Все неквалифицированные вызовы методов отправляются текущему экземпляру, как и любые ссылки на переменные экземпляра (которые выглядят как @this
).
Однако def
не является вызовом метода. Целью для методов, созданных def
, является текущий класс (или модуль), который можно найти с помощью Module.nesting [0]
.
Давайте посмотрим, как два разных eval разновидности влияют на эти области:
String.class_eval {[self, Module.nesting [0]]} Все неквалифицированные вызовы методов отправляются текущему экземпляру, как и любые ссылки на переменные экземпляра (которые выглядят как
@this
).
Однако def
не является вызовом метода. Целью для методов, созданных def
, является текущий класс (или модуль), который можно найти с помощью Module.nesting [0]
.
Давайте посмотрим, как два разных eval разновидности влияют на эти области:
String.class_eval {[self, Module.nesting [0]]} Все неквалифицированные вызовы методов отправляются текущему экземпляру, как и любые ссылки на переменные экземпляра (которые выглядят как
@this
).
Однако def
не является вызовом метода. Целью для методов, созданных def
, является текущий класс (или модуль), который можно найти с помощью Module.nesting [0]
.
Давайте посмотрим, как два разных eval разновидности влияют на эти области:
String.class_eval {[self, Module.nesting [0]]}
=> [Строка, Строка]
String.instance_eval {[сам, Module.nesting [0]]}
=> [Строка, # <Класс: Строка>]
В обоих случаях область действия экземпляра - это объект, для которого вызывается * _eval.
Для class_eval
область действия класса также становится целевым объектом, поэтому def
создает методы экземпляра для этого класса / модуля.
Для instance_eval
областью действия класса становится одноэлементный класс (также известный как метакласс, собственный класс) целевого объекта. Методы экземпляра, созданные в одноэлементном классе для объекта, становятся одноэлементными методами для этого объекта. Одноэлементные методы для класса или модуля - это то, что обычно (и несколько неточно) называется методами класса .
Область действия класса также используется для разрешения констант. Переменные класса ( @@ these @@ things
) разрешаются с помощью области действия класса, но они пропускают одноэлементные классы при поиске в цепочке вложенности модулей.