Newbie: pinpoint my mistake please..

D

dobest03

Hello.

Can anyone pinoint me where I made a mistake?

Error message is as follows:
accounts.rb(main):038:0> accounts.transferToSavings(100)
NoMethodError: undefined method `balance' for 0:Fixnum
from accounts.rb:29:in `debit'
from accounts.rb:29:in `transferToSavings'
from accounts.rb:42
from :0

But if I commented out "ths doesn't works" and remove comments
on "this works" codes, it works. Don't the code

@checking = super(checking)
@savings = super(savings)

create a new 'Account' class instances and stores them into
instance variable of class 'Accounts' @checking and @savings
respectively?

class Account
def initialize(balance)
@balance = balance
end
attr_reader :balance
attr_writer :balance
end

class Accounts < Account
attr_reader :checking, :savings
def initialize(checking, savings)
# these doesn't works
@checking = super(checking)
@savings = super(savings)
# but these works
# @checking = checking
# @savings = savings
end
private
def debit(account, amount)
account.balance -= amount
end
def credit(account, amount)
account.balance += amount
end
public
def transferToSavings(amount)
# private method can be called only in the defining class
debit(@checking, amount)
credit(@savings, amount)
end
end

# this doesn't work
accounts = Accounts.new(0, 10000)
# this works
#accounts = Accounts.new(Account.new(0), Account.new(10000))
accounts.balance # balance is the instance method of class 'Account'
accounts.balance = 100
accounts.checking
accounts.savings
accounts.transferToSavings(100)
accounts.checking
accounts.savings

Thanks a lot
SYLee
 
C

Chris Pine

Can anyone pinoint me where I made a mistake?

Well, I can try to explain why you are getting your error, or I can
tell you what *really* went wrong... :)

The main problem, the part that is confusing me (and you, I think,
though you might not know it yet) is this part:

class Accounts < Account

From what I gather, you are saying that a set of two accounts is a
"kind of" an account. This is not really the relationship you want to
express, though. Accounts "has multiple of" Account. (In general, I
find that there are very few places in which you want to use
inheritance when you are starting out... I can't remember the last
time I used it outside of writing GUI code.)

So, without giving away too much (because sometimes less teaching
means more learning :) I'd say try again, but make Accounts it's own
class (no inheritance) with either two instance variables set to
Account.new(whatever), or an array of accounts, or even a hash with
something like {'checking' =3D> Account.new(something), 'savings' =3D>
Account.new(something_else)}, depending on how you see it being used.

And definitely let us know if you get stuck again! It's hard to know
how much to "give away", but we're always happy to help.

Happy Rubying,

Chris
 
J

James Britt

dobest03 said:
Hello.

Can anyone pinoint me where I made a mistake?

Error message is as follows: ...
But if I commented out "ths doesn't works" and remove comments
on "this works" codes, it works. Don't the code

@checking = super(checking)
@savings = super(savings)

create a new 'Account' class instances and stores them into
instance variable of class 'Accounts' @checking and @savings
respectively?


Calling 'super' invokes the method of the same name in the parent class.
So, calling 'super' here invoke the method 'initialize' in Account.
But 'initialize' does not return a new instance of the class; the method
'new' does. (Calling 'new' makes a call to 'allocate', then calls
'initialize' on the object just allocated, and then returns the new
object. )

You may be better off removing the inheritance and simply using

@checking = Account.new( checking )
@savings = Account.new( savings )

James
--

http://www.ruby-doc.org
http://www.rubyxml.com
http://catapult.rubyforge.com
http://orbjson.rubyforge.com
http://ooo4r.rubyforge.com
http://www.jamesbritt.com
 
D

dobest03

Chris Pine 작성:
So, without giving away too much (because sometimes less teaching
means more learning :)

I see.. Right.
I'd say try again, but make Accounts it's own
class (no inheritance) with either two instance variables set to
Account.new(whatever), or an array of accounts, or even a hash with
something like {'checking' => Account.new(something), 'savings' =>
Account.new(something_else)}, depending on how you see it being used.

Thanks. I tried all the suggested way and succeeded the test..
 
D

dobest03

Chris Pine 작성:
And definitely let us know if you get stuck again! It's hard to know
how much to "give away", but we're always happy to help.

Happy Rubying,

Chris

I'd like to do happy-rubying.. :)

I wrote Accounts class for testing the private method scope as is
written
in the online book "Programming Ruby: Pragramatic ..." But in the
course
of the testing I've come across the problem as I questioned before.

Because the problem's gone, I'd like to ask questions as I intended
in the first place. Please bear with me If my question is a really
newbie
one.

This is a excerpt from the "Access Control" section of
"Classes,Objects,and Variables":
If a method is private, it may be called only within the context of the
calling
object--it is never possible to access another object's private method
directly,
even if the object is of the same class as the caller.

So... Could you explain the concept more clearly:
"within the context of the callling object"
?

And how can I write a statement which acess another object's private
method
directly?

If I define the class like this:
class A
private
def privAMethod
end
end

we can make a new instance

a = A.new()

but, can't call the private method.

a.privAMethod

In the above "a.privAMethod" is a expression that access its own
private method
(anyway though this is not allowed)
, not another objects.

Does it make any sense to say "accessing another objects private
method"?
Any such expression example?

Hmm. maybe this is not an important question nor worth being asked...


Thanks a lot.
SYLee.
 
C

Chris Pine

Sorry I'm taking so long to reply. I've been away from the list for a bit.
This is a excerpt from the "Access Control" section of
"Classes,Objects,and Variables":
If a method is private, it may be called only within the context of the
calling
object--it is never possible to access another object's private method
directly,
even if the object is of the same class as the caller.
=20
So... Could you explain the concept more clearly:
"within the context of the callling object"
?

All code is executed within the context of some object; i.e. some
object is doing the calling. Generally, the object doing the calling
is the object whose method is being called. In other words, you can
loosely translate "within the context of the callling object" as
"within a method of that object". More accurately, the current
context-object is always stored in the special variable 'self'.

And how can I write a statement which acess another object's private
method
directly?

Well, you can't; not really. That's the whole difference between
public and private methods. Make the method public if you want
someone else to have access to it, because that's what 'public' means.

If I define the class like this:
class A
private
def privAMethod
end
end
=20
we can make a new instance
=20
a =3D A.new()
=20
but, can't call the private method.
=20
a.privAMethod
=20
In the above "a.privAMethod" is a expression that access its own
private method
(anyway though this is not allowed)
, not another objects.

No, the current object (in whose context this code is executed) is not
'a'. Try this:

p self

That will show you the context object. This is the object that is
trying to call a's private method. Only 'a' can call it's own private
methods (like in a public instance method, called by another object).=20
For example:

# Untested code...
class A
def pubAMethod
privAMethod
end

private

def privAMethod
end
end

a =3D A.new
a.pubAMethod


Another way of thinking about it is that public methods can be called
by specifying the object whose method it is, followed by a dot (.) and
the method name. Like with 'a.pubAMethod'. But with private methods,
you aren't allowed to specify the object, so no "a.whatever" allowed.=20
You have to call it from inside the object. In fact, you'll even get
an error if you say 'self.privAMethod'... you aren't allowed to
specify the object at all.

Hope that helps,

Chris
 
G

gene.tani

maybe look at "Head First Design Patterns" (OReilly) or Shalloway/Trott
"Design Patterns Explained", both quite excellent books.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top