2016-05-03 3 views
1

Я хочу создать пустой массив как переменную экземпляра класса в Ruby. Однако мой текущий метод, похоже, не работает.Как инициализировать массивы классов в Ruby

Вот мой код:

class Something 
    @something = [] 
    def dosomething 
     s = 5 
     @something << s 
    end 
end 

Когда я вызываю функцию, она дает мне неопределенный метод отслеживающий. Однако, если я делаю что-то подобное с переменным класса, т.е .:

class Something 
    @@something = [] 
    def dosomething 
     s = 5 
     @@something << s 
    end 
end 

Это отлично работает.

Я знаю, что могу использовать метод initialize для создания пустого списка для @something, но есть ли другой способ сделать это без использования метода initialize? И почему это работает для переменных класса?

EDIT: Исправлена ​​опечатка

+0

* «без использования метода инициализации» * - есть ли причина, чтобы избежать 'initialize'? – Stefan

+0

Вопрос в том, что вы хотите инициализировать переменную экземпляра класса, а не переменную экземпляра, а не переменную класса. Однако вы назначили greenie на ответ, который не ссылается на переменные экземпляра класса. Зачем? btw, некоторые Rubiests * никогда * не используют переменные класса, всегда выбирая вместо этого переменные экземпляра класса. –

ответ

4

Вы должны использовать инициализацию в качестве конструктора, как показано ниже коды, и есть ли причина, почему не использовать инициализацию/конструктора. И пожалуйста исправить ошибки опечатки в определении класса Class Something к class Something не верблюду случая или первой буквы прописных букв, а в классе

class Something 
     def initialize 
     @something = Array.new 
     end 
     def dosomething 
     s = 5 
     @something << s 
     end 
    end 

переменная класса @@ доступна для охвата всего класса. поэтому они работают в коде, и если вы хотите использовать переменную экземпляра @, вам необходимо инициализировать ее, как указано выше. Переменная экземпляра доля с экземпляром/объекты класса

для получения более подробной информации перейдите по ссылке Ruby initialize method

+0

Обычно '[]' предпочтительнее 'Array.new', если вы не делаете что-то, что связано с передачей аргументов' new', например 'Array.new (10)'. – tadman

+0

Да, и в приведенном выше случае не было смысла отправлять аргументы :), поэтому я предпочитаю Array.new .. –

+0

Это ваши личные предпочтения, но большинство рубиновых стилей нахмурились, как бесполезный беспорядок. – tadman

2

На первом у вас есть опечатка. Изменить Class на class. Далее я предлагаю использовать метод initialize. При создании нового объекта это идеальное место для инициализации переменных экземпляра.

class Something 
    @@my_class_variable = [1] 

    def initialize 
    @something = [] 
    end 

    def dosomething 
    s = 5 
    @something << s 
    end 

    def self.get_my_class_variable 
    @@my_class_variable 
    end 
end 

Ваш сценарий будет прочитан и выполнен сверху вниз и после этого вы можете получить доступ к классу Something. Пока анализатор читает ваш скрипт/класс/модуль, вы можете определить переменные класса (@@), выполнить mixins и расширить класс с помощью других модулей. Вот почему вы можете определить переменную класса, но вы не можете определить переменную экземпляра. Потому что на самом деле у вас нет объекта-объекта из вашего класса. У вас есть только объект класса. В рубине все - объект. И ваш объект класса имеет определенную переменную класса:

Something.get_my_class_variable 
# => [1] 

Теперь вы можете создать экземпляр из своего класса. С помощью метода Something.new вызывается метод initialize и определяется ваша переменная экземпляра.

something = Something.new 
something.dosomething 
# => [5] 

Позже, если вы познакомились с этим вы можете определить методы получения и установки с attr_reader, attr_writer и attr_accessor, например, объектами или cattr_reader, cattr_writer и cattr_accessor для объектов класса.Например:

class Something 
    attr_reader :my_something 

    def initialize 
    @my_something = [] 
    end 

    def dosomething 
    s = 5 
    @my_something << s 
    end 
end 

something = Something.new 
something.my_something 
# => [] 
something.dosomething 
# => [5] 
something.my_something 
# => [5] 
+0

Хорошо, спасибо за это. Знаете ли вы, почему мой код работает для переменных класса? – Shwunky

+1

@Shwunky Так как переменные класса работают. Переменные класса предназначены для использования в контексте класса (а не в контексте экземпляра), и поэтому Ruby предоставляет вам возможность инициализировать их при создании класса. –

+0

@jordan Спасибо! Это дало понять. – Shwunky

0

Ваша проблема в попытке получить доступ к @something в методе экземпляра является то, что в рамках методов экземпляра, @ переменных относится к переменному экземпляру, и ваш @something является классом переменным а экземпляра.

@ переменные являются переменными экземпляра экземпляра, который является self, когда они созданы. Когда @something был создан, self был классом Something, а не экземпляр Кое-что, что было бы в случае метода экземпляра.

Как получить доступ к переменной экземпляра класса в методе экземпляра? Как и обычные переменные экземпляра, это должно быть сделано с помощью метода, как в attr_accessor. Один из способов сделать это состоит в использовании class << self сказать интерпретатор Ruby, что приложенный код должен быть оценен с классом (а не экземпляр) как само собой:

class C 

    @foo = 'hello' 

    class << self 
    attr_accessor :foo # this will be a class method 
    end 

    def test_foo # this is, of course, an instance method 
    puts self.class.foo # or puts C.foo 
    end 
end 

Мы можем показать, что это работает в IRB:

2.3.0 :005 > C.foo 
=> "hello" 
2.3.0 :006 > C.new.test_foo 
hello 
0

Вы правильно создали переменную экземпляра класса, @something и инициализировали ее пустым массивом. Есть два способа для экземпляров получить или изменить значение этой переменной. Одним из них является использование методов Object#instance_variable_get и Object#instance_variable_set (вызываются на классе):

class Something 
    @something = [] 
    def dosomething 
    s = 5 
    self.class.instance_variable_get(:@something) << s 
    end 
end 

sthg = Something.new 
sthg.dosomething  

Something.instance_variable_get(:@something) 
    #=> 5 

Другой способ заключается в создании аксессора переменной. Существует несколько способов сделать это. Я предпочитаю следующее:

Something.singleton_class.send(:attr_accessor, :something) 
Something.something #=> [5] 

В вашем методе dosomething можно было бы написать:

self.class.something << s 
Смежные вопросы