0

I want to leverage class methods on child classes in ruby, but those that rely on child instance variables are not working. I was told "don't use class variables! (@@)", so I'm not. How can I make class B do what I want, namely print out "1"?

class A
  @a = "1"

  def initialize
    self.class.what_is_a
  end

  def self.what_is_a
    p @a
  end
end

class B < A
end


A.what_is_a
B.what_is_a
A.new
B.new

The output:

"1"
nil
"1"
nil

I'd like them all to be "1".

skaz
  • 21,962
  • 20
  • 69
  • 98
  • 1
    hello, have you considered using protected methods instead of instance variables? – Bohdan Apr 28 '17 at 11:06
  • Can you show me how that would work? – skaz Apr 28 '17 at 11:15
  • Well, depending on the exact usecase, class variables might be the appropriate solution here. `B` is a different instance than `A`, so no wonder you don't get "1". It is not clear what you _actually_ want to do, so I can't offer any alternatives. – Sergio Tulentsev Apr 28 '17 at 11:24
  • I thought I explained what I want to do. I want B to print out "1". That is to say, I want B to have access to As class state. – skaz Apr 28 '17 at 11:36
  • Possible duplicate of [Inherit class-level instance variables in Ruby?](http://stackoverflow.com/questions/10728735/inherit-class-level-instance-variables-in-ruby) – Gerry Apr 28 '17 at 12:09
  • "I want B to have access to As class state" - easy, you can refer to instance of A from within B by using `superclass`. For example: https://pastebin.com/uD9UHRbK. – Sergio Tulentsev Apr 28 '17 at 12:40
  • That makes sense - I just thought it was kind of hacky...I figured I would get this pass through inheritance for free. There is no easy way to do what I want without having to write that kind of code in all child classes? – skaz Apr 28 '17 at 12:48
  • @skaz: yep, inheritance does not apply here. You want to access another object's state, you need to explicitly address the object. – Sergio Tulentsev Apr 28 '17 at 12:49
  • @SergioTulentsev Ahh, ok. So when I inherit A from B and make an instance, A and B is one object with shared state, and their classes are each objects as well with their own states, is that right? – skaz Apr 28 '17 at 13:04
  • *"those that rely on child instance variables are not working"* -- `@a = "1"` inside class `A` doesn't create an instance property. Move the assignment inside `initialize` to get an instance property. – axiac Apr 28 '17 at 13:10
  • @skaz: not really, A and B __are__ classes/objects, each with their own state. – Sergio Tulentsev Apr 28 '17 at 13:21
  • @axiac: nope, that'd make instance variable. He wants class instance variable. – Sergio Tulentsev Apr 28 '17 at 13:23
  • @SergioTulentsev But then wouldn't the same logic apply if A and B are two objects? You said "You want to access another object's state"... Wouldn't this also be accessing another object's state, if B is a different object: `class B attr_reader :a def initialize @a = 1 end end class A < B end ` puts A.new.a puts B.new.a And yet inheritance works here. It isn't clear to me why it doesn't work on the class level. I would expect the same thing to happen. EDIT: not sure how to format better... – skaz Apr 28 '17 at 13:33
  • @skaz: "And yet inheritance works here" - nope, state is not inherited in this example (or ever). _Behaviour_ is. When initializer is executed, it defines instance variable `@a` on __whatever__ is the current object (instance of `A` or `B`, in this case). – Sergio Tulentsev Apr 28 '17 at 13:51
  • @skaz: it may not make any sense right now. But don't worry, it will "click" one day :) – Sergio Tulentsev Apr 28 '17 at 14:03
  • There is no such thing as a "class instance variable". Classes are objects like any other object, they can have instance variables just like any other object. Instance variables belong to instances (objects). `A` and `B` are different objects, they cannot access each other's instance variables. – Jörg W Mittag Apr 28 '17 at 14:20
  • @JörgWMittag: it's an instance variable on a class object. Making it... "class instance variable"? :) Pedantry aside (you're right there, of course), we need a short name for this type of variables, to tell them apart from the "regular" instance variables, even if the name is not entirely accurate. – Sergio Tulentsev Apr 28 '17 at 15:52

1 Answers1

0

Using protected methods

class A   
  def initialize
    self.class.what_is_a
  end

  def self.what_is_a
    puts a
  end

  protected 

  def self.a
    '1'
  end
end

class B < A
end


A.what_is_a # >> 1
B.what_is_a # >> 1
A.new # >> 1
B.new # >> 1
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
Bohdan
  • 8,298
  • 6
  • 41
  • 51