Как создать "@property" и "@ property =", которые на самом деле являются методами - PullRequest
0 голосов
/ 15 марта 2020

Был ли способ превратить @property в метод с set и get, поэтому @property вызовет метод вместо возврата фактического свойства, а @property = someval также вызовет метод вместо присвоения фактическому свойству?

В моем проекте объекты хранят значения в базе данных. Рассмотрим этот простой модуль базы данных, который хранит записи в памяти. В моем реальном проекте это DBM, подобная PostgreSQL:

module MyDB
    RECORDS = {}

    def self.create(pk)
        RECORDS[pk] ||= {}
    end

    def self.set(pk, key, val)
        return RECORDS[pk][key] = val
    end

    def self.get(pk, key)
        return RECORDS[pk][key]
    end
end

У объектов есть поля, которые хранятся в этой базе данных. Итак, в этом классе поле species хранится и извлекается из базы данных:

class Pet
    def initialize(pk)
        @pk = pk
        MyDB.create(@pk)
    end

    def species=(val)
        MyDB.set @pk, 'breed', val
    end

    def species()
        return MyDB.get(@pk, 'breed')
    end
end

Простое использование класса Pet может выглядеть так:

motley = Pet.new('motley')
motley.species = 'cat'

Это работает в настоящее время, но здесь я столкнулся с раздражением. Я сделал что-то подобное в классе:

def some_method(newval)
    @species = newval
end

Затем, когда я запустил код, я получил такой результат:

motley.some_method 'whatever'
puts motley.species #=> cat

Затем я понял, что это не было ошибкой, а я должен был сделать это:

def some_method(newval)
    self.species = newval
end

Я думаю, @species = newval имеет смысл. Он чувствует как будто я устанавливаю свойство объекта.

Это был способ присвоения методу свойству, что-то вроде:

def :@species=(val)
    return MyDB.set(@pk, 'breed', 'val')
end

def :@species
    return MyDB.get(@pk, 'breed')
end

Is Есть ли способ сделать такую ​​вещь? Должно ли быть?

1 Ответ

6 голосов
/ 15 марта 2020

Есть ли способ сделать такое?

Нет. В Ruby методы setter и getter - это способ получить / установить внутреннее состояние объекта. Переменные экземпляра - это просто лексические переменные, которые относятся к экземпляру.

Ruby - это язык, основанный на передаче сообщений, и @foo = bar отправляет сообщение =, bar получателю, который является лексической переменной @foo. Если вместо этого вызвать self#@foo=, это сломает всю модель языка.

Должно ли это быть?

Ад №

  • Нужна ли нам совершенно новая языковая функция только потому, что вам трудно вспомнить вызов self.foo= вместо @foo =? Нет.
  • Добавит ли эта функция что-нибудь к языку, который уже нельзя сделать? Нет.
  • Это нарушит существующий код? Да .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...