Я опытный программист Obj-C/Java, и я попал в Ruby. Очевидно, тот факт, что он настолько динамичен, замечателен (повторное открытие классов - это классно!), Но есть одна вещь, которая меня беспокоит/беспокоит, когда я начинаю писать код Ruby.Явное определение класса iVar в Ruby (ala Obj-C)
Мне было бы интересно узнать, что вы, например, Ruby-ers, явно задаете тип iVars в своих классах. Из того, что я вижу, вы можете установить iVar на любой объект, и рубин не будет жаловаться. Но если вы ожидаете, что определенный iVar будет иметь определенный тип, это может вызвать проблемы в строке. Например:
class MyString
def initialize(myString)
@myString = myString
end
def uppercase_my_string
@myString.upcase
end
end
st1 = MyString.new("a string!")
st1.uppercase_my_string
st2 = MyString.new(["a string"])
st2.uppercase_my_string
Этот код будет бросать NoMethodError
, так как, конечно, массив не имеет какого-либо метода upcase
. К сожалению, он не говорит нам, где мы действительно ошибались (строка выше, при создании str2
), поэтому нам не очень помогают при отладке (если str2
создается несколько модулей в некотором неприметном месте) Один естественный шаг может чтобы добавить некоторые проверки initialize
следующим образом:
class MyString
def initialize(myString)
raise TypeError, "myString iVar is not a string!" unless myString.class == String
@myString = myString
end
end
...same code as before
Отлично, теперь, если мы случайно создать новый MyString мы рассказали, как глупо мы были (и что еще более важно, что мы сказали, когда мы делаем это и не тогда, когда мы Моя следующая проблема заключается в том, когда мы решили использовать attr_accessors
на iVar.
class MyString
attr_accessor :my_string
def initialize(my_string)
raise TypeError, "myString iVar is not a string!" unless my_string.class == String
@my_string = my_string
end
def uppercase_my_string
@my_string.upcase
end
end
st1 = MyString.new("a string!")
st1.uppercase_my_string
st2 = MyString.new("good, it's a string")
st2.my_string = ["an array!"]
st2.uppercase_my_string
Используя установленный сеттер, мы можем быть очень проницательным и обходим проверку ошибок в initialize
. Еще раз у этой проблемы возникает исключение в uppercase_my_string
, а не когда мы случайно установили @my_string
в массив.
Наконец, мы могли бы создать аксессуаров вручную и добавить проверку ошибок, но это огромная боль ... есть более быстрый и простой способ сделать это. Или я просто застенчивый и недостаточно динамичный?
Спасибо!
стороны: Я знаю, что в Obj-C вы все еще имеете те же проблемы во время выполнения, но обычно вы заметили ошибку компилятора говоря, вы присваиваете объект типа array
переменного типа string
(или что-то подобное), поэтому, по крайней мере, мы предупреждаем, где это происходит
«Вы не беспокоитесь о типах, которые много в Ruby, вы беспокоитесь о том, какие методы что-то реагируют» - какие методы что-то реагирует на *, - это его тип. –
Спасибо, я так и думал, но просто подумал, есть ли способ - похоже, нет, но, скорее всего, потому, что это не рубиноподобно. Хорошая точка в методе 'is_?', Я буду использовать это в будущем для проверки классов/членов классов. – Patrick
В Ruby есть много DWIM (и, как и большинство вещей, это хорошо и плохо :) Вообще-то вы использовали бы более узкий 'response_to?' В пользу 'is_a?'; конечно, в реальном мире вы должны быть практичными и делать то, что работает. –