Sök…


Syntax

  • klassnamn
  • # någon kod som beskriver klassbeteendet
  • slutet

Anmärkningar

Klassnamn i Ruby är konstanter, så den första bokstaven borde vara en stor bokstav.

class Cat # correct
end  

class dog # wrong, throws an error
end

Skapa en klass

Du kan definiera en ny klass med class nyckelord.

class MyClass
end

När den har definierats kan du skapa en ny instans med .new metoden

somevar = MyClass.new
# => #<MyClass:0x007fe2b8aa4a18>

Konstruktör

En klass kan bara ha en konstruktör, det vill säga en metod som kallas initialize . Metoden startas automatiskt när en ny instans av klassen skapas.

class Customer
  def initialize(name)
     @name = name.capitalize 
  end
end

sarah = Customer.new('sarah')
sarah.name #=> 'Sarah'

Klass- och instansvariabler

Det finns flera speciella variabeltyper som en klass kan använda för att lättare dela data.

Instansvariabler, föregående av @ . De är användbara om du vill använda samma variabel på olika metoder.

class Person
  def initialize(name, age)
    my_age = age # local variable, will be destroyed at end of constructor
    @name = name # instance variable, is only destroyed when the object is
  end

  def some_method
    puts "My name is #{@name}." # we can use @name with no problem
  end
   
  def another_method
    puts "My age is #{my_age}." # this will not work!
  end
end

mhmd = Person.new("Mark", 23)

mhmd.some_method #=> My name is Mark.
mhmd.another_method #=> throws an error

Klassvariabel, föregående av @@ . De innehåller samma värden i alla instanser av en klass.

class Person
  @@persons_created = 0 # class variable, available to all objects of this class
  def initialize(name)
    @name = name

    # modification of class variable persists across all objects of this class
    @@persons_created += 1
  end  
      
  def how_many_persons
    puts "persons created so far: #{@@persons_created}"
  end 
end
    
mark = Person.new("Mark")
mark.how_many_persons #=> persons created so far: 1
helen = Person.new("Helen")

mark.how_many_persons #=> persons created so far: 2
helen.how_many_persons #=> persons created so far: 2
# you could either ask mark or helen

Globala variabler, föregående av $ . Dessa är tillgängliga var som helst för programmet, så se till att använda dem klokt.

$total_animals = 0

class Cat
  def initialize
    $total_animals += 1
  end
end

class Dog
  def initialize
    $total_animals += 1
  end
end

bob = Cat.new()
puts $total_animals #=> 1
fred = Dog.new()
puts $total_animals #=> 2

Få åtkomst till instansvariabler med getters och seters

Vi har tre metoder:

  1. attr_reader : används för att tillåta read av variabeln utanför klassen.
  2. attr_writer : används för att tillåta ändring av variabeln utanför klassen.
  3. attr_accessor : kombinerar båda metoderna.
class Cat
  attr_reader :age # you can read the age but you can never change it
  attr_writer :name # you can change name but you are not allowed to read
  attr_accessor :breed # you can both change the breed and read it

  def initialize(name, breed)
    @name = name
    @breed = breed
    @age = 2 
  end
  def speak
    puts "I'm #{@name} and I am a #{@breed} cat"
  end
end
 
my_cat = Cat.new("Banjo", "birman")
# reading values:

my_cat.age  #=> 2
my_cat.breed #=> "birman"
my_cat.name #=> Error

# changing values
 
my_cat.age = 3 #=> Error
my_cat.breed = "sphynx" 
my_cat.name = "Bilbo"

my_cat.speak #=> I'm Bilbo and I am a sphynx cat

Observera att parametrarna är symboler. detta fungerar genom att skapa en metod.

class Cat
  attr_accessor :breed
end

Är i princip samma som:

class Cat
  def breed
    @breed
  end
  def breed= value
    @breed = value
  end
end

Åtkomstnivåer

Ruby har tre åtkomstnivåer. De är public , private och protected .

Metoder som följer de private eller protected nyckelorden definieras som sådana. Metoder som kommer före dessa är implicit public metoder.

Offentliga metoder

En offentlig metod ska beskriva beteendet hos objektet som skapas. Dessa metoder kan kallas utanför det skapade objektets räckvidd.

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

  def speak
    puts "I'm #{@name} and I'm 2 years old"
  end
  
  ...
end

new_cat = Cat.new("garfield")
#=> <Cat:0x2321868 @name="garfield">
 
new_cat.speak
#=> I'm garfield and I'm 2 years old

Dessa metoder är offentliga rubinmetoder, de beskriver beteendet för att initialisera en ny katt och beteendet för talmetoden.

public nyckelord är onödigt, men kan användas för att undvika private eller protected

def MyClass
  def first_public_method
  end

  private

  def private_method
  end

  public

  def second_public_method
  end
end

Privata metoder

Privata metoder är inte tillgängliga utanför objektet. De används internt av objektet. Använda kattexemplet igen:

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

  def speak
    age = calculate_cat_age # here we call the private method 
    puts "I'm #{@name} and I'm #{age} years old"
  end

  private
     def calculate_cat_age
       2 * 3 - 4 
     end
end

my_cat = Cat.new("Bilbo")
my_cat.speak #=> I'm Bilbo and I'm 2 years old
my_cat.calculate_cat_age #=> NoMethodError: private method `calculate_cat_age' called for #<Cat:0x2321868 @name="Bilbo">

Som ni kan se i exemplet ovan har den nyskapade Cat objekt tillgång till calculate_cat_age metoden internt. Vi tilldelar variabeln age till följd av att köra privata calculate_cat_age metod som skriver ut namn och ålder för katten att konsolen.

När vi försöker ringa calculate_cat_age metoden utanför my_cat objektet får vi en NoMethodError eftersom det är privat. Förstår?

Skyddade metoder

Skyddade metoder liknar mycket privata metoder. De kan inte nås utanför objektet på samma sätt som privata metoder inte kan vara. Men med hjälp av self ruby-metoden kan skyddade metoder kallas inom ramen för ett objekt av samma typ.

class Cat
  def initialize(name, age)
    @name = name
    @age = age
  end

  def speak
    puts "I'm #{@name} and I'm #{@age} years old"
  end

  # this == method allows us to compare two objects own ages. 
  # if both Cat's have the same age they will be considered equal.
  def ==(other)
     self.own_age == other.own_age
  end

  protected
     def own_age
        self.age
     end
end

cat1 = Cat.new("ricky", 2)
=> #<Cat:0x007fe2b8aa4a18 @name="ricky", @age=2>

cat2 = Cat.new("lucy", 4)
=> #<Cat:0x008gfb7aa6v67 @name="lucy", @age=4>

cat3 = Cat.new("felix", 2)
=> #<Cat:0x009frbaa8V76 @name="felix", @age=2>

Du kan se att vi har lagt till en åldersparameter till kattklassen och skapat tre nya kattobjekt med namn och ålder. Vi kommer att kalla own_age för att jämföra åldern hos våra kattobjekt.

cat1 == cat2
=> false

cat1 == cat3
=> true

Titta på det, vi kunde hämta cat1s ålder med den skyddade metoden self.own_age och jämföra den mot cat2: s ålder genom att ringa cat2.own_age inuti cat1.

Klassmetoder

Klasserna har tre typer av metoder: instans, singleton och klassmetoder.

Instansmetoder

Det här är metoder som kan kallas från en instance av klassen.

class Thing
  def somemethod
    puts "something"
  end
end

foo = Thing.new # create an instance of the class
foo.somemethod # => something

Klassmetod

Dessa är statiska metoder, dvs de kan åberopas på klassen och inte på en instansering av den klassen.

class Thing
  def Thing.hello(name)
    puts "Hello, #{name}!"
  end
end

Det motsvarar att använda self i stället för klassnamnet. Följande kod motsvarar koden ovan:

class Thing
  def self.hello(name)
    puts "Hello, #{name}!"
  end
end

Åkalla metoden genom att skriva

Thing.hello("John Doe")  # prints: "Hello, John Doe!"

Singleton-metoder

Dessa är endast tillgängliga för specifika instanser i klassen, men inte för alla.

# create an empty class
class Thing
end

# two instances of the class
thing1 = Thing.new
thing2 = Thing.new

# create a singleton method
def thing1.makestuff
  puts "I belong to thing one"
end

thing1.makestuff # => prints: I belong to thing one
thing2.makestuff # NoMethodError: undefined method `makestuff' for #<Thing>

Både singleton och class kallas eigenclass es. I grund och botten, vad rubin gör är att skapa en anonym klass som har sådana metoder så att den inte stör de instanser som skapas.

Ett annat sätt att göra detta är av class << -konstruktören. Till exempel:

# a class method (same as the above example)
class Thing
  class << self # the anonymous class
    def hello(name)
      puts "Hello, #{name}!"
    end
  end
end

Thing.hello("sarah") # => Hello, sarah!

# singleton method

class Thing
end

thing1 = Thing.new

class << thing1
  def makestuff
    puts "I belong to thing one"
  end
end

thing1.makestuff # => prints: "I belong to thing one"

Dynamisk klassskapning

Klasser kan skapas dynamiskt genom användning av Class.new .

# create a new class dynamically
MyClass = Class.new

# instantiate an object of type MyClass
my_class = MyClass.new

I exemplet ovan skapas en ny klass och tilldelas konstant MyClass . Denna klass kan instanseras och användas precis som alla andra klasser.

Metoden Class.new accepterar en Class som blir superklass för den dynamiskt skapade klassen.

# dynamically create a class that subclasses another
Staffy = Class.new(Dog)

# instantiate an object of type Staffy
lucky = Staffy.new
lucky.is_a?(Staffy) # true
lucky.is_a?(Dog)    # true

Metoden Class.new accepterar också ett block. Blockets sammanhang är den nyskapade klassen. Detta gör det möjligt att definiera metoder.

Duck = 
  Class.new do
    def quack
      'Quack!!'
    end
  end

# instantiate an object of type Duck
duck = Duck.new
duck.quack # 'Quack!!'

Nytt, allokera och initiera

På många språk skapas nya instanser av en klass med ett speciellt new nyckelord. I Ruby används också new för att skapa instanser av en klass, men det är inte ett nyckelord; istället är det en statisk / klassmetod som inte skiljer sig från någon annan statisk / klassmetod. Definitionen är ungefär denna:

class MyClass
   def self.new(*args)
     obj = allocate
     obj.initialize(*args) # oversimplied; initialize is actually private
     obj
   end
end

allocate utför den verkliga "magin" att skapa en oinitialiserad instans av klassen

Observera också att returvärdet för initialize kastas och obj returneras istället. Detta gör det omedelbart klart varför du kan koda din initieringsmetod utan att oroa dig för att återvända self i slutet.

Den "normala" new metoden som alla klasser får från Class fungerar som ovan, men det är möjligt att omdefiniera den du vill, eller definiera alternativ som fungerar annorlunda. Till exempel:

class MyClass
  def self.extraNew(*args)
    obj = allocate
    obj.pre_initialize(:foo)
    obj.initialize(*args)
    obj.post_initialize(:bar)
    obj
  end
end


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow