2009-07-28 13 views

Odpowiedz

28

atrybuty są specyficzne właściwości obiektu. Metody to możliwości obiektu.

W Ruby wszystkie zmienne instancji (atrybuty) są domyślnie prywatne. Oznacza to, że nie masz do nich dostępu poza zakresem samej instancji. Jedynym sposobem uzyskania dostępu do atrybutu jest użycie metody dostępowej.

class Foo 
    def initialize(color) 
    @color = color 
    end 
end 

class Bar 
    def initialize(color) 
    @color = color 
    end 

    def color 
    @color 
    end 
end 

class Baz 
    def initialize(color) 
    @color = color 
    end 

    def color 
    @color 
    end 

    def color=(value) 
    @color = value 
    end 
end 

f = Foo.new("red") 
f.color # NoMethodError: undefined method ‘color’ 

b = Bar.new("red") 
b.color # => "red" 
b.color = "yellow" # NoMethodError: undefined method `color=' 

z = Baz.new("red") 
z.color # => "red" 
z.color = "yellow" 
z.color # => "yellow" 

Ponieważ jest to naprawdę commmon zachowanie, Ruby zapewnia jakąś wygodną metodę definiowania metody dostępowe: attr_accessor, attr_writer i attr_reader.

+1

Zawsze można uzyskać dostęp do zmiennej przy użyciu Object.instance_variable_get (: symbol @), który omija potrzebę zdefiniowania akcesorów. –

+6

To nie jest dobra praktyka. ;) instance_variable_get powinno być zarezerwowane dla metaprogramowania. To tak, jak definiowanie metody jako prywatnej, a następnie dostęp do niej za pomocą metody send (:). –

38

Atrybuty to tylko skrót. Jeśli użyjesz attr_accessor do utworzenia atrybutu, Ruby po prostu zadeklaruje zmienną instancji i utworzy dla ciebie metody getter i setter.

Ponieważ poprosiłeś dla przykładu:

class Thing 
    attr_accessor :my_property 

    attr_reader :my_readable_property 

    attr_writer :my_writable_property 

    def do_stuff 
     # does stuff 
    end 
end 

Oto jak chcesz użyć klasy:

# Instantiate 
thing = Thing.new 

# Call the method do_stuff 
thing.do_stuff 

# You can read or write my_property 
thing.my_property = "Whatever" 
puts thing.my_property 

# We only have a readable accessor for my_readable_property 
puts thing.my_readable_property 

# And my_writable_propety has only the writable accessor 
thing.my_writable_property = "Whatever" 
+3

Myślę, że jest to znacznie lepsza odpowiedź niż zatwierdzona odpowiedź ... –

4

Atrybuty są, ściśle rzecz biorąc, zmiennymi instancji klasy. Mówiąc bardziej ogólnie, atrybuty są zwykle deklarowane przy użyciu metod typu attr_X, podczas gdy metody są po prostu deklarowane jako is.

Prostym przykładem może być:

attr_accessor :name 
attr_reader :access_level 

# Method 
def truncate_name! 
    @name = truncated_name 
end 

# Accessor-like method 
def truncated_name 
    @name and @name[0,14] 
end 

# Mutator-like method 
def access_level=(value) 
    @access_level = value && value.to_sym 
end 

Rozróżnienie między tymi dwoma jest nieco arbitralne w Ruby, ponieważ nie ma bezpośredniego dostępu do nich została szczegółowo uregulowana. To kontrastuje dość mocno z innymi językami, takimi jak C, C++ i Java, gdzie dostęp do właściwości obiektów i metod wywoływania odbywa się za pośrednictwem dwóch różnych mechanizmów. Java w szczególności ma metody accessor/mutator, które są zapisane jako takie, podczas gdy w Ruby są one implikowane przez nazwę.

Często zdarza się tak, jak w przykładzie, że różnica między "akcesoriem atrybutu" a metodą użytkową dostarczającą dane na podstawie wartości atrybutu, takiej jak nazwa skrócona, jest niewielka.

1
class MyClass 
    attr_accessor :point 

    def circle 
    return @circle 
    end 

    def circle=(c) 
    @circle = c 
    end 
end 

Atrybut jest właściwością obiektu. W tym przypadku używam metody klasy attr_accessor do zdefiniowania właściwości: point wraz z niejawnymi metodami getter i setter dla punktu.

obj = MyClass.new 
obj.point = 3 
puts obj.point 
> 3 

Metoda "circle" jest jawnie zdefiniowanym programem pobierającym dla zmiennej instancji @circle. "circle =" jest zdefiniowanym jawnie zmiennym dla zmiennej instancji @circle.

0

Słyszałem, że słowo "atrybut" odnosi się, w kręgach specyficznych dla Ruby, do dowolnej metody, która nie przyjmuje argumentów.

class Batman 

    def favorite_ice_cream 
    [ 
     'neopolitan', 
     'chunky monkey', 
     'chocolate', 
     'chocolate chip cookie dough', 
     'whiskey' 
    ].shuffle[0]   
    end 

end 

W powyższym przypadku atrybut my_newest_batman.favorite_ice_cream byłby atrybutem.

Powiązane problemy