Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

276
Vistas
¿Cómo las diferentes formas de definir una clase influyen en la forma en que funciona include?

Tengo un módulo simple que define una constante y la hace privada:

 module Foo Bar = "Bar" private_constant :Bar end

Puedo incluirlo en una clase como esta, y funciona como se esperaba:

 class User include Foo def self.test Bar end end puts User.test # => Bar begin User::Bar rescue => exception puts "#{exception} as expected" # => private constant Foo::Bar referenced as expected end

(Llamémoslo definición de "clase típica")

Luego probé el enfoque Class.new , pero falló miserablemente:

 X = Class.new do include Foo def self.test Bar # Line 28 pointed in the stack trace end end begin X::Bar rescue => exception puts "#{exception}" # => private constant Foo::Bar end puts X.test # test.rb:28:in `test': uninitialized constant Bar (NameError) # from test.rb:28:in `<main>'

¿Por qué? Siempre pensé que class Something y Something = Class.new son equivalentes. ¿Cuál es la diferencia real?

Luego tuve un golpe de inspiración y recordé que hay una forma alternativa de definir los métodos de clase, que realmente funcionó:

 X = Class.new do class << self include Foo def test Bar end end end begin X::Bar rescue => exception puts "#{exception}" # => uninitialized constant X::Bar end puts X.test # Bar

Nuevamente, ¿por qué funciona este y por qué la excepción ahora es diferente: private constant Foo::Bar frente a la uninitialized constant X::Bar ?

Parece que esas 3 formas de inicializar clases difieren de una manera matizada.

  1. hace exactamente lo que quiero: la barra es accesible internamente, y acceder a ella da una excepción sobre la referencia a la constante privada.
  2. el segundo da la excepción "ok", pero no tiene acceso a Bar en sí
  3. tercero tiene acceso, pero ahora da una excepción ligeramente diferente

¿Qué está pasando exactamente aquí?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Esta es una de las mayores trampas en Ruby: el alcance de la definición constante es parcialmente sintáctico , es decir, depende de cómo esté estructurado el código que lo rodea.

 module Foo Bar = "Bar" end

Bar está dentro de una definición de module , por lo que se define en ese módulo.

 class << self include Foo end

Bar se incluye dentro de una definición de class , por lo que se define en esa clase.

 Class.new do include Foo end

No hay una class o module adjunto (esta es una llamada de método normal con un bloque), por lo que la constante se define en el nivel superior.

En cuanto a su tercer error, creo que se debe a que la constante se definió en la clase singleton (eso es lo que es la class << self ) frente a la clase misma. Son dos objetos de clase separados.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda