tags:

views:

218

answers:

6

Sorry about the wording of the question, I don't really know how to put it. What I mean is, how could I do this:

class Test
  def doSomething
    puts "I'm working"
  end
end

class numberTwo
  def doSomethingElse
    subject.doSomething
    puts "Doing other things"
  end
end
subject = Test.new
otherObject = numberTwo.new
otherObject.doSomethingElse

What I want is when otherObject.doSomethingElse is called, subject.doSomething to also be called. I'm not sure how you can do this, or if it is possible. Thanks in advance.

A: 

I'm not sure if this is what you mean, but you can create a class method:

class Test
  def self.doSomething
    puts "I'm working"
  end
end

That should let you call that method without instantiating an object. But then your subject.doSomething line should be Test.doSomething .

Sorry if I misunderstood your question.

Jorge Israel Peña
A: 

Change "subject" to "$subject" and you're all set.

glenn mcdonald
I dunno which coward dinged this without explaining. The $ on $subject makes this a global variable, which can be used from anywhere. It a testing context this may be exactly what you want: a single object accumulating logging messages or errors or timings or whatever as your other methods fire...But provide a little more detail on *why* you're trying to do this and you'll definitely get better advice...
glenn mcdonald
A: 

If you want a class to call a member of another class, you have to make the class a member of the first class, or derive from that class.

Here your numberTwo class tries to call a method on an object that it has no reference to (subject).

JRL
+1  A: 

If you want a method in one class to know about an instance of another class (an instance is created when you call "new", and assigned to a variable, like subject), the variable either needs to

a) be global, as glenn mcdonald indicated by suggesting you use $subject. The $ indicates a global variable

b) be a member of the class from which your calling, so it would not be created outside the class. So subject would be a member variable of NumberTwo, and initialized in NumberTwo's constructor perhaps

c) be passed in as a parameter.

It seems to me that the easiest way given what you're showing us, would be to pass in subject as a parameter.

class NumberTwo
  def doSomethingElse(subject)
     subject.doSomething
  end
end

subject = Test.new
otherObject = numberTwo.new
otherObject.doSomethingElse(subject)
Derek
+1  A: 

You need to make a decision between calling a method on an instance of Test or just making it a class method and calling that. If it's the former, then you need to hold a reference somewhere so the calling method can see it. There are several ways to do this.

  • provide the reference to NumberTwo#initialize or some other attribute writer
  • allocate Test in a factory method of NumberTwo
  • use a global variable to hold a reference

There are already examples of everything but the factory method, so I will do that one...

class NumberTwo
  def doSomethingElse
    @myTest.doSomething
    puts "Doing other things"
  end
  def testFactory
    @myTest = Test.new
  end
end
otherObject = NumberTwo.new
subject = otherObject.testFactory
otherObject.doSomethingElse
DigitalRoss
A: 

The otherObject object needs some way to know about the something object. The scope of the method declaration as you have it prevents the class from knowing about something when the method is created. Here's one possible solution:

class Foo
  def doSomething
    puts "I'm working"
  end
end
class Bar
  attr_accessor :foo
  def doSomethingElse
    foo.doSomething unless foo.nil?
    puts "Doing other things"
  end
end
foo = Foo.new
bar = Bar.new
bar.foo = foo
bar.doSomethingElse
jtbandes