2016-12-07 11 views
3

私はクラスの外のメソッドからクラス変数にアクセスしようとしています。ルビの外部からクラス変数にアクセスするには?

これが私のクラスである:

class Book 

    @@bookCount = 0 
    @@allBooks = [] 

    def self.allBooks 
    @@allBooks 
    end 

    def self.bookCount 
    @@bookCount 
    end 

    attr_accessor :name,:author,:date,:genre,:rating 

    def initialize(name, author, date, genre, rating) 
     @name = name 
     @author = author 
     @date = date 
     @genre = genre 
     @rating = rating 
     @@bookCount += 1 
     @@allBooks << self 
    end 

end 

これはクラス変数にアクセスしようとする方法である@@はbookcount

def seeBookShelf 
    if @@bookCount == 0 
    puts "Your bookshelf is empty." 
    else 
    puts "You have " + @bookCount + " books in your bookshelf:" 
    puts allBooks 
    end 
end 

私はこれを取得する方法を実行しようとすると:

undefined local variable or method `bookCount' for main:Object (NameError) 

外部からbookCountにアクセスするにはどうすればよいですか?

+1

最初の質問:なぜクラス変数を使用していますか?これらは、クラスとインスタンス間の情報を、しばしば懸念の混乱につながる方法で共有します。 'self.class.allBooks'は直接アクセスするよりも優れています。 – tadman

+3

Rubyの規約では、 'see_book_shelf'のスタイルで変数名やメソッド名に大文字を使わずに名前を付けることを強くお勧めします。クラスには大文字と小文字が混在しています。 – tadman

+1

作成されたブックインスタンスの参照が保持されるため、これは基本的にメモリの問題を求めています。この責任をBookのクラスレベルに委譲するのではなく、Bookを格納することを特に目的としたBookShelfクラスを作成する方がよいでしょう。 – tadman

答えて

0

あなたは、変数のクラスを指定する必要があります。クラスの外のクラス変数にアクセスするために

def seeBookShelf 
    if Book.bookCount == 0 
    puts "Your bookshelf is empty." 
    else 
    puts "You have " + Book.bookCount + " books in your bookshelf:" 
    puts Book.allBooks 
    end 
end 
+0

しかし、変数に直接アクセスするのは悪い方法です。クラスにゲッタを追加する必要があります。または、新しいクラスBookShelfを作成して、すべてのブックを保存します。 – Gregory

+0

'self.class'もこれがインスタンスメソッドにある場合はここで動作します。 – tadman

2

使用class_variable_getを:

class Foo 
    @@a = 1 
end 

Foo.class_variable_get(:@@a) 
=> 1 
+0

技術的には正解ですが、助言もありません。 'class_variable_get'メソッドは、汎用目的のプログラミングではなく、リフレクションのためのものです。 – tadman

0

あなたはクラス変数にアクセスするためのゲッターを必要とし、このコードを試してください。 説明はhttp://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/を参照してください。 文字列補間を使用する方が良い場合は、タイプエラーが発生します。また、Rubyesqueが多くなります。

class Book 
    @@bookCount = 0 

    def self.bookCount 
    @@bookCount 
    end 
end 

def seeBookShelf 
    if Book.bookCount == 0 
    puts "Your bookshelf is empty." 
    else 
    puts "You have #{Book.bookCount} books in your bookshelf:" 
    end 
end 

seeBookShelf # Your bookshelf is empty. 
+0

@グレゴリーとほぼ同じ答えでした。 – Ilya

+0

ええ、私たちは同じ時間に腹を立てていました。私は自分の答えを試して全体の実行可能な部分として公開したいのですが、しばしば誰かに速く殴られました。私のソリューションはIlyaよりも優れています。 bookcount> 0のときにエラーが発生しましたか? – peter

0

あなたは、特定のクラスの範囲内で、コードのブロックを評価するためにclass_evalを使用することができます。

class Book 
    @@bookCount = 1 
end 

Book.class_eval '@@bookCount' 
# => 1 

そして、ちょうど楽しみのために...あなたが実際にclass_eval

と策略のすべての種類を行うことができます
Book.class_eval { @@bookCount = 5 } 
Book.class_eval '@@bookCount' 
# => 5 

Book.class_eval do 
    def self.hey_look_a_new_method 
    return "wow" 
    end 
end 

Book.hey_look_a_new_method 
# => "wow" 
1

ほとんどの場合、クラスインスタンス変数がクラス変数より優先されます。後者は、継承で使用すると、すべてのやり方で奇妙な振る舞いをする傾向があります。

は考えてみましょう:

class Book 
    @book_count = 0 
    @all_books = [] 

    class << self 
    attr_reader :book_count 
    attr_reader :all_books 
    end 

    # further code omitted. 

end 

Book.book_countとBook.all_booksが予想されるデータを取得し、このコードで。

関連する問題