Las clases son un concepto central en la programación orientada a objetos. En Crystal, todo es un objeto, cada objeto tiene un tipo y puede responder a algunos métodos. Las clases son planos para crear objetos: proporcionan valores iniciales para el estado, como las variables, y las implementaciones del comportamiento, como los métodos. Los objetos son instancias de una clase que contienen todas las variables de instancia y los estados.
Una clase se define con la palabra clave class, seguida del nombre de la clase escrito en UpperCamelCase.
class Account
end
Para crear una instancia de una clase, llama al nombre de la clase usando el método new.
class Account
end
account = Account.new
En el ejemplo anterior, la variable account es una instancia de la clase Account.
Al crear una instancia, un método especial llamado initialize actúa como constructor.
Se llama cuando se crea una instancia.
El constructor te permite establecer el estado inicial de la instancia.
El método initialize puede recibir argumentos, que se pasan al crear una instancia.
class Account
def initialize(number)
5 + number # => 9
end
end
Account.new(4)
El método initialize no puede devolver un valor manualmente; en su lugar, new devuelve la instancia recién creada.
class Account
def initialize(number)
5 + number
end
end
Account.new(4)
# => #<Account:0x7f5dc33dcea0>
Un método de instancia es un método que está disponible para una instancia de una clase y que se puede llamar en esa instancia.
Los métodos de instancia se definen con la palabra clave def, seguida del nombre del método.
Se definen dentro de la definición de la clase.
class Account
def balance
100
end
end
account = Account.new
account.balance # => 100
Las variables de instancia son variables que están disponibles en todos los métodos de la instancia.
Para acceder a una variable de instancia, necesitas definir un método de instancia.
Se pueden inicializar en el método initialize.
Se definen con el prefijo @.
class Account
def initialize
@balance = 100
end
def balance
@balance
end
end
account = Account.new
account.balance
# => 100
Las variables de instancia también se pueden definir dentro de la definición de la clase.
class Account
@age = 0
end
Las variables de instancia se pueden inicializar con un argumento que se pasa al método initialize.
Como Crystal no puede inferir el tipo del argumento que se usa durante la inicialización, hay que especificarlo.
Si quieres leer más sobre esto, puedes consultar: inferencia de tipos.
Para especificar el tipo de la variable puedes usar el símbolo :, seguido del tipo.
Por ejemplo, si quieres crear una variable de instancia llamada balance de tipo Int32, puedes hacer lo siguiente: @balance : Int32.
O, si quieres crear una variable de instancia llamada raining de tipo Bool, puedes hacer lo siguiente: @raining : Bool.
Hay varias formas de implementar esto: una es declarar el argumento con su tipo en el método initialize y luego asignar el argumento a la variable de instancia, como en el siguiente ejemplo:
class Account
def initialize(balance : Int32)
@balance = balance
end
def balance
@balance
end
end
account = Account.new(1)
account_2 = Account.new(5)
account.balance
# => 1
account_2.balance
# => 5
Otra forma es declarar el tipo de la variable de instancia en la definición de la clase con la forma @<variable> : <Type>, como en el siguiente ejemplo:
class Weather
@raining : Bool
def initialize(raining)
@raining = raining
end
def raining
@raining
end
end
weather = Weather.new(true)
weather.raining
# => true
Los métodos pueden modificar variables de instancia. Estos métodos se pueden llamar en la instancia de la clase. Cuando un método modifica una variable de instancia, ese cambio solo está disponible en la instancia de la clase en la que lo llamaste.
class Account
def initialize(balance : Int32)
@balance = balance
end
def withdraw(amount)
@balance -= amount
end
def balance
@balance
end
end
account = Account.new(10)
account_2 = Account.new(10)
account.balance
# => 10
account_2.balance
# => 10
account.withdraw(5)
account.balance
# => 5
account_2.balance
# => 10
Los métodos de clase son métodos que se definen para una clase, pero no para sus instancias.
Ofrecen una forma de crear métodos que no dependen del estado de la instancia.
Se definen con la palabra clave def, seguida de self.<method name>.
self es una referencia al espacio de nombres desde el que se llama a self.
En este caso, se refiere a la clase Account.
Sería lo mismo que escribir Account., pero self. es la forma preferida.
class Account
def self.balance
100
end
end
Account.balance
# => 100
Tu amigo Johannes ama hacer hardware DIY (hazlo tú mismo). Acaba de construir una máquina de jugos, y eso le hace mucha ilusión. La meta de Johannes es poder preparar jugo fresco cada mañana.
La máquina de jugos de Johannes tiene muchas funcionalidades sofisticadas. Como un sistema de medición integrado, que puede decirte cuánto jugo hay en el vaso. También tiene un temporizador, que te dice cuánto tiempo lleva funcionando la máquina.
Johannes no es el mejor programando, pero quiere hacer un programa para controlar la máquina. Por eso te pidió que le ayudaras.
La máquina tiene una luz de debug, es un mecanismo simple: si la máquina tiene corriente, la luz de debug está encendida. El programa solo se ejecutará si la luz de debug está encendida.
Este método debe ser un método de clase llamado JuiceMaker.
Define el método de clase JuiceMaker.debug_light_on? que devuelve true.
JuiceMaker.debug_light_on?
#=> true
Cuando la máquina se enciende, debe crear una instancia de una clase llamada JuiceMaker.
Se supone que la máquina tiene un estado inicial.
El estado inicial debe contener la siguiente información:
false cuando la máquina se enciende.Define el estado inicial, que toma la cantidad de jugo en el vaso como parámetro, y construye el estado inicial.
El estado inicial debe contener una variable de instancia @running que se establece en false, y una variable de instancia @fluid que se basa en un argumento dado cuando se inicializa la clase.
JuiceMaker.new(5)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=5>
La máquina se puede encender y apagar.
Necesitas definir un método para encender la máquina.
Cuando la máquina se enciende, el estado de funcionamiento debe establecerse en true.
Define el método JuiceMaker#start que enciende la máquina.
juice_maker = JuiceMaker.new(5)
juice_maker.start
juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=true, @fluid=5>
La máquina debe poder decirte cuál es su estado.
Debe devolver true si la máquina está funcionando, y false si no está funcionando.
Define el método JuiceMaker#running? que devuelve el estado de la máquina.
juice_maker = JuiceMaker.new(5)
juice_maker.start
juice_maker.running?
#=> true
La máquina puede agregar jugo al vaso. La máquina puede decir cuánto jugo se agrega al vaso. La máquina necesita ayuda para saber cuánto jugo hay en el vaso después de agregar el jugo.
Define el método JuiceMaker#add_fluid, que toma la cantidad de jugo agregada como parámetro y actualiza la cantidad de jugo en el vaso.
juice_maker = JuiceMaker.new(5)
juice_maker.add_fluid(5)
juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=10>
La máquina se puede encender y apagar.
Necesitas definir un método para apagar la máquina
Este método solo se llamará cuando la máquina esté funcionando.
Cuando la máquina se apaga, el estado de funcionamiento debe establecerse en false.
La máquina también necesita ayuda para determinar cuánto jugo hay en el vaso después de apagarse.
La máquina usa cinco unidades de jugo por minuto.
Define el método JuiceMaker#stop, que toma el número de minutos que la máquina ha estado funcionando como parámetro y devuelve la cantidad de jugo en el vaso después de apagar la máquina.
juice_maker = JuiceMaker.new(5)
juice_maker.start
juice_maker
#=> <JuiceMaker:0x10f0b8 @running=true, @fluid=5>
juice_maker.stop(1)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=0>
Regístrate en Exercism para aprender y dominar Crystal con 26 conceptos142 ejercicios y mentoría humana real, todo gratis.