2013-05-20 16 views
18

widzę kod jak:Mieszając attr_accessor oraz metody initialize w jednej klasie

class Person 
    def initialize(name) 
    @name = name 
    end 
end 

Rozumiem to pozwala mi robić takie rzeczy jak person = Person.new i używać @name gdzie indziej w mojej klasie, podobnie jak inne metody. Potem widziałem jak kod:

class Person 
    attr_accessor :name 
end 

... 

person = Person.new 
person.name = "David" 

jestem tylko na straty z tych dwóch metod siatki. Jakie są szczególne zastosowania def initialize(name)? Przypuszczam, że attr_accessor pozwala mi czytać i pisać. Oznacza to, że są to dwie oddzielne metody. Tak? Chcesz uzyskać wyjaśnienia na temat def initialize i attr_accessor oraz w jaki sposób się zazębiają.

Odpowiedz

21

initialize i attr_accessor mają nic wspólnego ze sobą. attr_accessor :name tworzy kilka metod:

def name 
    @name 
end 

def name=(val) 
    @name = val 
end 

Jeśli chcesz ustawić nazwy podczas tworzenia obiektu, można to zrobić w inicjalizatorze:

def initialize(name) 
    @name = name 
    # or 
    # self.name = name 
end 

Ale nie musisz tego robić. Możesz ustawić nazwę później, po utworzeniu.

p = Person.new 
p.name = "David" 
puts p.name # >> "David" 
+1

Rozumiem. Metoda inicjalizacyjna służy do inicjowania wartości podczas tworzenia obiektów. Nie jest to konieczne, ale jeśli obiekt ma wiele atrybutów, ma sens, aby móc zrobić to wszystko naraz, zamiast tracić czas i ustawić wszystkie atrybuty później, po stworzeniu. Tak? – David

+0

@Do sortowania. Ograniczeniem jest to, że jeśli obiekt ma wiele atrybutów, inicjator szybko staje się bezużytecznym bałaganem uporządkowanych parametrów. Właśnie dlatego (a) mamy teraz nazwane parametry i/lub (b) możesz użyć map, aby zwiększyć czytelność w miejscu budowy. –

+0

@DaveNewton czy masz bardzo krótki przykład obu? Chyba wiem, co masz na myśli, ale chcesz być pewny. Kiedy mówisz, że mamy teraz nazwane parametry, czy sugerujesz, że kiedyś tak było? Jak inaczej moglibyśmy powiedzieć "chcę wziąć ten i ten parametr" podczas definiowania metody? – David

14

Oto odpowiedź, której szukasz Classes and methods. Przeczytaj uważnie.

Oto dobra dokumentacja z linku:

Klasy i metody

Teraz jesteśmy gotowi, aby stworzyć własną klasę adresową. Zacznijmy proste. Zacznijmy od adresu, który zawiera tylko pole "ulica".

ten sposób można zdefiniować klasę:

class Address 
    def initialize(street) 
     @street = street 
    end 
end 

Chodźmy przez to:

  • Słowo kluczowe klasa definiuje klasę.

  • Definiując metodę wewnątrz tej klasy, kojarzymy ją z tą klasą.

  • Metoda inicjalizacji jest tym, co faktycznie konstruuje strukturę danych. Każda klasa musi zawierać metodę initialize.

@street jest zmienną obiektową. Podobne do klawiszy skrótu. Znak @ wyróżnia @street jako zmienną obiektową. Za każdym razem, gdy tworzysz obiekt klasy Adres, ten obiekt będzie zawierał zmienną @street.

Użyjmy tej klasy, aby utworzyć obiekt adresu.

address = Addres.new("23 St George St.") 

To wszystko. adres jest teraz obiektem klasy Adres Odczytywanie danych w obiekcie

Załóżmy, że chcemy odczytać dane w obiekcie adresu. Aby to zrobić, musimy napisać metodę zwracającą te dane:

class Address 
    def initialize(street) 
     @street = street 
    end 

    # Just return @street 
    def street 
     @street 
    end 
end 

Teraz metoda Adres # ulica umożliwia odczytanie ulicy adresu. In irb:

>> address.street 
=> "23 St George St." 

Właściwość obiektu widoczna na zewnątrz nazywana jest atrybutem. W tym przypadku street jest atrybutem. W szczególności jest to atrybut czytelny.Ponieważ ten rodzaj atrybutu jest bardzo powszechne, Ruby oferuje skrót poprzez słowo kluczowe attr_reader:

class Address 
    attr_reader :street 
    def initialize(street) 
     @street = street 
    end 
end 

Zmiana danych w obiekcie

Możemy również zdefiniować metodę, aby zmienić dane w obiekcie.

class Address 
    attr_reader :street 
    def initialize(street) 
     @street = street 
    end 
    def street=(street) 
     @street = street 
    end 
end 

Ruby jest całkiem mądry w jego wykorzystania ulicy = metoda:

`address.street = "45 Main St`." 

Zauważ że można umieścić obowiązuje BETTEN ulicę i =. Teraz, gdy możemy zmienić dane adresowe, możemy uprościć metodę inicjalizacji i ustawić domyślną ulicę na pusty ciąg "".

class Address 
    attr_reader :street 
    def initialize 
     @street = "" 
    end 
    def street=(street) 
     @street = street 
    end 
end 

address = Address.new 
address.street = "23 St George St." 

To może nie wydawać się dużo uproszczeń, ale gdy dodamy miasto, stan i ZIP pola i więcej metod uczyni to definicja klasy nieco prostsze.

Teraz ulica jest również atrybutem zapisywalnym. Tak jak poprzednio, można zadeklarować je jako takie z attr_writer:

class Address 
    attr_reader :street 
    attr_writer :street 
    def initialize 
     @street = "" 
    end 
end 

dostępu do danych

Bardzo często trzeba atrybuty, które są oba atrybuty odczytu i zapisu. Ruby pozwala je scalić razem z attr_accessor. Sądzę, że nazywałoby się to "dostępnymi atrybutami", ale nigdy nie widziałem, żeby tak się nazywało.

class Address 
    attr_accessor :street 
    def initialize 
     @street = "" 
    end 
end 

Dzięki tej wiedzy łatwo jest teraz zdefiniować całą strukturę książki adresowej. Jak się okazuje, attr_accessor i znajomi akceptują wiele argumentów.

class Address 
    attr_accessor :street, :city, :state, :zip 
    def initialize 
     @street = @city = @state = @zip = "" 
    end 
end 
+3

Proszę podać faktyczną treść w odpowiedzi, a nie tylko podać link. Odpowiedzi dotyczące wyłącznie linków są niezadowolone, ponieważ: (a) odpowiedzi nie są same w sobie, oraz (b) jeśli link się obniża, jest gorszy niż bezużyteczny. –

+3

Okay! dając :) –

+0

@DaveNewton Gotowe. Czy muszę jeszcze coś dodawać? proszę skomentuj. –

4

myślę rozważyć initialize jako konstruktor. Mówiąc dokładniej, nie jest. Domyślnym konstruktorem jest metoda new na klasie, a metoda initialize jest wywoływana przez tę metodę. Jeśli nie zdefiniujesz initialize, nadal możesz utworzyć obiekt z new, ponieważ initialize nie jest samym konstruktorem. W takim przypadku domyślna initialize nic nie robi. Jeśli zdefiniujesz initialize, zostanie to wywołane zaraz po utworzeniu obiektu.

Zestawienie @foo = ... i attr_accessor :foo są różne.Pierwszy przypisuje wartość do zmiennej instancji @foo, podczas gdy ta druga umożliwia dostęp do @foo za pomocą metod foo i foo=. Bez tego można nadal uzyskać dostęp do @foo, bezpośrednio opisując to.

-1

przeciwieństwie do C++, Java zmienne instancji w Ruby są prywatny domyślnie (częściowo, ponieważ mogą one być dostępne za pomocą a.instance_variable_get: @x)

np

class Dda 
    def initialize task 
     @task = task 
     @done = false 
    end 
    end 
item = Dda.new "Jogging" # This would call the initializer and task = Jogging would 
be set for item 
item.task # would give error as their is no function named task to access the instance 
variable. 

Chociaż mamy ustaw wartość elementu, ale nie będziemy w stanie nic z nią zrobić, ponieważ zmienne instace są prywatne w ruby. Kod dla getter:

def task 
    @task 
end 
#for getter 
def task=task 
    @task = task 
end 

Korzystanie getter by upewnić się, że item.task zwraca jego wartość i korzystania setter daje nam elastyczność w celu zapewnienia wartości do zmiennych instancji w dowolnym momencie.