Buscar..


Sintaxis

  • nombre de la clase
  • # algún código que describe el comportamiento de la clase
  • fin

Observaciones

Los nombres de las clases en Ruby son constantes, por lo que la primera letra debe ser mayúscula.

class Cat # correct
end  

class dog # wrong, throws an error
end

Creando una clase

Puede definir una nueva clase utilizando la palabra clave de class .

class MyClass
end

Una vez definido, puede crear una nueva instancia usando el método .new

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

Constructor

Una clase solo puede tener un constructor, es decir, un método llamado initialize . El método se invoca automáticamente cuando se crea una nueva instancia de la clase.

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

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

Variables de clase e instancia

Hay varios tipos de variables especiales que una clase puede usar para compartir datos más fácilmente.

Variables de instancia, precedidas por @ . Son útiles si desea utilizar la misma variable en diferentes métodos.

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

Variable de clase, precedida por @@ . Contienen los mismos valores en todas las instancias de una clase.

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

Variables globales, precedidas por $ . Estos están disponibles en cualquier parte del programa, así que asegúrese de usarlos sabiamente.

$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

Acceso a variables de instancia con captadores y definidores.

Tenemos tres métodos:

  1. attr_reader : se utiliza para permitir read la variable fuera de la clase.
  2. attr_writer : se utiliza para permitir la modificación de la variable fuera de la clase.
  3. attr_accessor : combina ambos métodos.
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

Tenga en cuenta que los parámetros son símbolos. Esto funciona creando un método.

class Cat
  attr_accessor :breed
end

Es básicamente lo mismo que:

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

Niveles de acceso

Ruby tiene tres niveles de acceso. Son public , private y protected .

Los métodos que siguen a las palabras clave private o protected se definen como tales. Los métodos que vienen antes de estos son métodos implícitamente public .

Métodos Públicos

Un método público debe describir el comportamiento del objeto que se está creando. Estos métodos se pueden llamar desde fuera del alcance del objeto creado.

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

Estos métodos son métodos públicos de rubí, describen el comportamiento para inicializar un nuevo gato y el comportamiento del método de hablar.

public palabra clave public es necesaria, pero puede usarse para escapar de forma private o protected

def MyClass
  def first_public_method
  end

  private

  def private_method
  end

  public

  def second_public_method
  end
end

Métodos privados

Los métodos privados no son accesibles desde fuera del objeto. Son utilizados internamente por el objeto. Usando el ejemplo del gato otra vez:

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">

Como puede ver en el ejemplo anterior, el objeto Cat recién creado tiene acceso al método calculate_cat_age internamente. Asignamos la age variable al resultado de ejecutar el método private calculate_cat_age que imprime el nombre y la edad del gato en la consola.

Cuando intentamos llamar al método calculate_cat_age desde fuera del objeto my_cat , recibimos un NoMethodError porque es privado. ¿Consíguelo?

Métodos protegidos

Los métodos protegidos son muy similares a los métodos privados. No se puede acceder a ellos fuera de la instancia del objeto de la misma manera que los métodos privados no pueden ser. Sin embargo, utilizando el método self ruby, los métodos protegidos pueden llamarse dentro del contexto de un objeto del mismo tipo.

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>

Puede ver que hemos agregado un parámetro de edad a la clase cat y que hemos creado tres nuevos objetos cat con el nombre y la edad. Vamos a llamar al método protegido own_age para comparar la edad de los objetos de nuestro gato.

cat1 == cat2
=> false

cat1 == cat3
=> true

Mire eso, pudimos recuperar la edad de cat1 utilizando el método self.own_age protected y compararla con la edad de cat2 llamando a cat2.own_age dentro de cat1.

Clases de métodos de clase

Las clases tienen 3 tipos de métodos: métodos de instancia, singleton y clase.

Métodos de instancia

Estos son métodos que se pueden llamar desde una instance de la clase.

class Thing
  def somemethod
    puts "something"
  end
end

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

Método de clase

Estos son métodos estáticos, es decir, pueden invocarse en la clase, y no en una instanciación de esa clase.

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

Es equivalente a usar self en lugar del nombre de la clase. El siguiente código es equivalente al código anterior:

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

Invoca el método escribiendo

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

Métodos singleton

Estos solo están disponibles para instancias específicas de la clase, pero no para todos.

# 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>

Tanto los métodos singleton como los de class se llaman eigenclass es. Básicamente, lo que hace Ruby es crear una clase anónima que contenga dichos métodos para que no interfiera con las instancias que se crean.

Otra forma de hacerlo es mediante la class << constructor. Por ejemplo:

# 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"

Creación dinámica de clases

Las clases se pueden crear dinámicamente mediante el uso de Class.new .

# create a new class dynamically
MyClass = Class.new

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

En el ejemplo anterior, se crea una nueva clase y se asigna a la constante MyClass . Esta clase puede ser instanciada y utilizada como cualquier otra clase.

El método Class.new acepta una Class que se convertirá en la superclase de la clase creada dinámicamente.

# 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

El método Class.new también acepta un bloque. El contexto del bloque es la clase recién creada. Esto permite definir métodos.

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

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

Nuevo, asignar e inicializar

En muchos idiomas, las nuevas instancias de una clase se crean utilizando una new palabra clave especial. En Ruby, new también se usa para crear instancias de una clase, pero no es una palabra clave; en cambio, es un método estático / clase, no es diferente de cualquier otro método estático / clase. La definición es aproximadamente esta:

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

allocate realiza la verdadera 'magia' de crear una instancia no inicializada de la clase

Tenga en cuenta también que el valor de retorno de initialize se descarta, y se devuelve obj en su lugar. Esto hace que sea inmediatamente claro por qué se puede codificar su método de inicialización sin tener que preocuparse acerca de regresar self al final.

El new método "normal" que todas las clases obtienen de la Class funciona como se indicó anteriormente, pero es posible redefinirlo como desee, o definir alternativas que funcionen de manera diferente. Por ejemplo:

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow