Inheriting variables, super, and "not super"?

  • Thread starter Hugh Sasse Staff Elec Eng
  • Start date
H

Hugh Sasse Staff Elec Eng

Is there a way in a method to say
"ignore this if called as super"?

I am trying to inherit variables from a superclass, but I may need
them different in the subclass, so I can't use class variables.

Instance variables are not passed on to subclasses, so to initialize
them I need to call super within initialize...

Also, at present, some of my initialization code sets up other
things which make sense for an instance of that class, but not when
I'm using an instance of a subclass.

Is there an idiom like

class Y < Z
def initialize()
@y_var = 0
if self.class == Y
y_init
end
end
end


class X < Y
def initialize
super
@x_var = 0
end
end

Or does this show I doing something horribly wrong?
To quote Dave Thomas in
http://www.codegeneration.net/tiki-...=9&PHPSESSID=a594d9ec9586b7a0e307f3f4f05e6a85

"You can sense the code's resistance: things that should be easy
turn our hard, and things that should be easy to change turn in to
nightmares.[...] Quite often the problem lies not with the details of
the code, but instead with something larger, such as the decision to
use a particular technique. "

This is what it feels like at the moment, but I can't see what else
I should be using.

For a bigger overview of my problem: I am trying to control an
application with a Hierarchical State Machine, and I am trying to
take advantage of the specialisation aspects of the class hierarchy
to create the states. I had to provide a mechanism to navigate
between states, so from that viewpoint the fit was imperfect. Now
it looks worse.

Any ideas? Apart from "If you're in a hole, stop digging" :)

Hugh
 
T

T. Onoma

Is there an idiom like

class Y < Z
def initialize()
@y_var = 0
if self.class == Y
y_init
end
end
end


class X < Y
def initialize
super
@x_var = 0
end
end

I'm not sure I understand you, but I'm interested in what it is you are
attempting. Might you not use a redefinable responder method? (aka don't
forget about our tusting duck typing ;)

class Y < Z
def initialize()
@y_var = 0
if initiator == Y
y_init
end
end
def initiator
Y
end
end

class X < Y
def initialize
super
@x_var = 0
end
def initiator
X
end
end

T.
Any ideas? Apart from "If you're in a hole, stop digging" :)

Dig to China! :)
 
I

Ian Hobson

Hugh Sasse Staff said:
Is there a way in a method to say
"ignore this if called as super"?
[Big snip]
Any ideas? Apart from "If you're in a hole, stop digging" :)

Hugh
Hi Hugh,

I think I have some idea of what you are trying to do, and perhaps some
understanding of how you got into the wrong hole.

Hint one - in trad programming you think of the data and how it needs to
be manipulated. For OO Programming you think of the package of
behaviours you need and create a class to behave in that way. Ignore the
data - it will fall out of the other thinking.

So. To your state machine.

I would set up the state machine as a tree (or network if you must),
where each node type is a different class. Inherit all (tree) nodes from
a node type that knows how to manage its children.

You can now walk the tree to change your state. At each node, you call a
method to handle what needs doing at that state. The problem with this
is that the code to handle all the types of state are scattered across
lots of classes. Yuck!

So in stead, you create a visitor class. This visits the node by sending

node.acceptVisit(self) to the node it wants to visit, which simply
calls

aVisitor.hasVisitedNodeType(self)

Where NodeType is different for each class of node. (This is called
double despatch.)

Then your visitor class has *all* the matching hasVisitedSomwhere
methods, to handle all the actions you need. The hasVisitedSomewhere
calls can have params to pass the information it needs, or it can pass
self as shown, and then visitor uses node's accessors.

This gives the visitor method all the info it needs to take its action,
and decide where to go next.

To use, you create a visitor and let it loose on the root node. It
crawls over the tree, going its job. The tree neither knows nor cares
who has visited.

To do another job, create a new visitor class.

Example - if the tree represented an expression, one visitor could
report it in infix notation, another generate code to compute it and a
third evaluate it directly, and a forth.... you get the idea.

Regards

Ian
 
H

Hugh Sasse Staff Elec Eng

Hugh Sasse Staff said:
Is there a way in a method to say
"ignore this if called as super"?
[Big snip]
Any ideas? Apart from "If you're in a hole, stop digging" :)

Hugh
Hi Hugh,

I think I have some idea of what you are trying to do, and perhaps some
understanding of how you got into the wrong hole.

Hint one - in trad programming you think of the data and how it needs to
be manipulated. For OO Programming you think of the package of
behaviours you need and create a class to behave in that way. Ignore the
data - it will fall out of the other thinking.

Yes, though I've not found the last bit comes so easily :)
So. To your state machine.

I would set up the state machine as a tree (or network if you must),
where each node type is a different class. Inherit all (tree) nodes from
a node type that knows how to manage its children.

Yes. That's my basic design....
You can now walk the tree to change your state. At each node, you call a
method to handle what needs doing at that state. The problem with this
is that the code to handle all the types of state are scattered across
lots of classes. Yuck!

Yes, but the code to handle each state is as local to that state as
possible, avoiding repetition of things in the ancestors. The
complexity *is* difficult (for me) to manage. It sounds like you are
saying this is not really a sad reflection of my ability to program,
which is encouraging!
So in stead, you create a visitor class. This visits the node by sending

node.acceptVisit(self) to the node it wants to visit, which simply
calls

aVisitor.hasVisitedNodeType(self)

Where NodeType is different for each class of node. (This is called
double despatch.)

I've encountered the term double dispatch in the context of nested
case statements, I think. I can't see how these are two
representations of the same thing... (That probably doesn't matter
here, anyway) The need for both calls is that the visitor may need
to tell the Node to give it some kinds of information, and to have
the Node call a method on the visitor means they both do "Tell,
Don't Ask"?
(http://www.pragmaticprogrammer.com/developers/ppllc/papers/1998_05.html)
Is that the idea? I've read about the visitor pattern but it has
not really clicked, with me.
Then your visitor class has *all* the matching hasVisitedSomwhere
methods, to handle all the actions you need. The hasVisitedSomewhere

So it "knows" about all the events the system can respond to,....
calls can have params to pass the information it needs, or it can pass
self as shown, and then visitor uses node's accessors.

...and where to send them in the current state?
This gives the visitor method all the info it needs to take its action,
and decide where to go next.

To use, you create a visitor and let it loose on the root node. It
crawls over the tree, going its job. The tree neither knows nor cares
who has visited.

To do another job, create a new visitor class.

Example - if the tree represented an expression, one visitor could
report it in infix notation, another generate code to compute it and a
third evaluate it directly, and a forth.... you get the idea.

So the visitor IS the current state? I'll have to re-read my [GOF]
in the light of this....
Regards

Ian

Hugh, pondering...
 
H

Hugh Sasse Staff Elec Eng

On Tuesday 09 December 2003 06:17 pm, Hugh Sasse Staff Elec Eng wrote:

I'm not sure I understand you, but I'm interested in what it is you are
attempting. Might you not use a redefinable responder method? (aka don't
forget about our tusting duck typing ;)

class Y < Z
def initialize()
@y_var = 0
if initiator == Y
y_init
end
end
def initiator
Y
end
end

class X < Y [...]
def initiator
X
end
end

Yes, that might be better. I wonder if we can avoid having to
repeat the method definition though?
T.


Dig to China! :)

I think from here (.ac.uk) it would be Australia :)
Hugh
 
I

Ian Hobson

Hi Hugh,

Hugh Sasse Staff said:
Hugh Sasse Staff said:
Is there a way in a method to say
"ignore this if called as super"?
[Big snip]
Any ideas? Apart from "If you're in a hole, stop digging" :)

Hugh
Hi Hugh,

I think I have some idea of what you are trying to do, and perhaps some
understanding of how you got into the wrong hole.

Hint one - in trad programming you think of the data and how it needs to
be manipulated. For OO Programming you think of the package of
behaviours you need and create a class to behave in that way. Ignore the
data - it will fall out of the other thinking.

Yes, though I've not found the last bit comes so easily :)
So. To your state machine.

I would set up the state machine as a tree (or network if you must),
where each node type is a different class. Inherit all (tree) nodes from
a node type that knows how to manage its children.

Yes. That's my basic design....
You can now walk the tree to change your state. At each node, you call a
method to handle what needs doing at that state. The problem with this
is that the code to handle all the types of state are scattered across
lots of classes. Yuck!

Yes, but the code to handle each state is as local to that state as
possible, avoiding repetition of things in the ancestors. The
complexity *is* difficult (for me) to manage. It sounds like you are
saying this is not really a sad reflection of my ability to program,
which is encouraging!
I didn't think it for a moment. State machines are hard!
I've encountered the term double dispatch in the context of nested
case statements, I think. I can't see how these are two
representations of the same thing... (That probably doesn't matter
here, anyway)
They are the same thing - the nested case statement is how it appears in
procedural form.
The need for both calls is that the visitor may need
to tell the Node to give it some kinds of information, and to have
the Node call a method on the visitor means they both do "Tell,
Don't Ask"?
(http://www.pragmaticprogrammer.com/developers/ppllc/papers/1998_05.html)
Is that the idea? I've read about the visitor pattern but it has
not really clicked, with me.
Yes, but weakly. If the visitor simply told the node it has been
visited, then the node would contain all the behaviour needed to act on
that event.

By moving all this code from the nodes to the visitor class, it becomes
much easier to write. But it does go a bit against tell, don't ask.
So it "knows" about all the events the system can respond to,.... Yep - all in one source file.


..and where to send them in the current state?
I think so in this case. Where to go next can be decided by the
visitor, the node or an external walker. To my mind, the flexibility
offered by having the visitor class decide is well worth it.
This gives the visitor method all the info it needs to take its action,
and decide where to go next.

To use, you create a visitor and let it loose on the root node. It
crawls over the tree, going its job. The tree neither knows nor cares
who has visited.

To do another job, create a new visitor class.

Example - if the tree represented an expression, one visitor could
report it in infix notation, another generate code to compute it and a
third evaluate it directly, and a forth.... you get the idea.

So the visitor IS the current state? I'll have to re-read my [GOF]
in the light of this....
Yes - the visitor and its internal state, are the current state.

Regards

Ian
 
S

Simon Strandgaard

Hugh Sasse Staff said:
On Wed, 10 Dec 2003, Ian Hobson wrote: [snip]
So the visitor IS the current state? I'll have to re-read my [GOF]
in the light of this....
Yes - the visitor and its internal state, are the current state.


Yes visitor holds the current state.

Its similar to sending a consultant into a big office, walking around from
cubicle to cubicle and collecting data. Finaly he comes out of the office
with the result.


Yesterday I did some experiments with some filesystem ideas, where I am
using visitor. You may want to check it out:
http://rubyforge.org/cgi-bin/viewcvs/cgi/viewcvs.cgi/projects/experiments/file_system/?cvsroot=ros

have a look at 'lookup.rb' and 'test_lookup.rb'
 
H

Hugh Sasse Staff Elec Eng

Hi Hugh,


I didn't think it for a moment. State machines are hard!

No, just how I felt about the experience. Yes, they seem to be
difficult, even though they simplify things!
They are the same thing - the nested case statement is how it appears in
procedural form.

After reading my [GOF] and the web somewhat I see how these relate
now.
The need for both calls is that the visitor may need
to tell the Node to give it some kinds of information, and to have
the Node call a method on the visitor means they both do "Tell,
Don't Ask"? [...]
Yes, but weakly. If the visitor simply told the node it has been
visited, then the node would contain all the behaviour needed to act on
that event.

By moving all this code from the nodes to the visitor class, it becomes
much easier to write. But it does go a bit against tell, don't ask.

It is possibly like the visitor Telling the node Tell me what you
want, rather than asking it "is this what you want"
Yep - all in one source file.

This was conterintuitive, normally you don't couple things that
tightly. I think I understand it better now. My problem now is
that I'm beginning to think I need triple dispatch. the state
classes, the visitor (the application), and the GUI, with the GUI
either as a collection of states or as another visitor to the state
heirarchy.
..and where to send them in the current state?
I think so in this case. Where to go next can be decided by the
visitor, the node or an external walker. To my mind, the flexibility
offered by having the visitor class decide is well worth it.
So the visitor IS the current state? I'll have to re-read my [GOF]
in the light of this....
Yes - the visitor and its internal state, are the current state.

I think this pattern will be really useful elsewhere in this
application as well, where all properties of each user must be
processed in various ways.
Regards

Ian
Thank you,
Hugh
 

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

Similar Threads


Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top