Thanks, Gary and James, for this input: there's something to work with now.
Beware though, Gary, you may have to steel yourself to throw away a lot
of what you've written! Also, you've chosen something quite complex
to model as an introduction to OO, so don't expect to make rapid
progress!
All of the following IMO only. Others will have different OO models.
James Edward Gray II wrote:
>
> On Jan 13, 2004, at 6:24 AM, Gary Stainburn wrote:
>
> [snip background]
>
> > 3) As everything else will be created from the Trainset instance, they
> > will
> > have a link to it. This will be stored as $self->{_OWNER}. This will
> > then
> > (hopefully) provide quick direct access to the Trainset variables
> > (were Class
> > globals). I think I should be able to simply call something like
> > $self->{_OWNER}{_BLOCKS}
>
> Or you could always do something like $self->{_Trainset}->get_blocks(),
> which is probably a little better style. Always use methods when you
> can.
I don't like this. The code in 'main' should keep track of which trainset
it's currently talking about. If nothing else, the back reference means we
have to write a DESTROY method :-/
The program should look something like this:
use strict;
use warnings;
use Trainset;
my $tset = new Trainset;
and thereafter use $tset as the 'current' trainset.
> > The example code (not tested yet) will create a long length of track
> > (TCB1 and
> > TCB2), and a siding (S1). It will then create a switch (Y-shape)
> > point and
> > connect that to TCB2 and S1.
> >
> > It will then create a signalbox, and in that signalbox create a lever
> > to
> > control the set of points.
> >
> > my $tset=Trainset->new;
> > $tset->add_track('TCB1','TCB'); # create 1st block of track
> > $tset->add_track('TCB2','TCB'); # create 2nd block of track
> > $tset->add_track('S1','TCB'); # create Siding 1
>
> An add_tracks() method might be handy. What's that second parameter,
> if I may ask?
I echo that: what's 'TCB'? Also, my code would read:
foreach (qw/ TCB1 TCB2 S1 /) {
my $track = new Trainset::Track($_);
$tset->add($track);
}
> > $points=$tset->add_point('GSP1','SWITCH'); # create switch point to
> > siding
> > $tset->add_link('TCB1',0,'TCB2',0); # link TCB1 (rear) to TCB2
> > (advance)
> > $tset->add_link('TCB2',0,'GSP1',0); # link TCB2 to points GSP1
> > $tset->add_link('S1',0,'GSP1',1); # link Siding1 to points GSP1
> > (offset1)
>
> Again, what are the number parameters?
>
> In my opinion the above could probably be done in one method call,
> which would make for a much nicer interface. Heck, have it create
> tracks too if the don't exist.
Yes. And I wonder if a 'link' should be a separate object or just
a relationship between two 'track' things?
My idea of how this code should look:
{
my $point = new Trainset::Point('GSP1');
$tset->add($point);
$tset->link('TCB1', 'TCB2');
$tset->link('S1', 'GSP1');
}
> > $box=$tset->add_signalbox('Grosmont'); # Create Grosmont signalbox
> > $lever=$tset->add_lever('GS1'); # Create lever GS1
> > $box->use_lever($lever,0); # Put lever1 in signalbox
>
> Again, too much work. The whole point of using the Trainset object as
> the code interface is to hide all these ugly details from users. Does
> a signal box always have at least one lever? Create it in the signal
> box constructor then. Or modify add_signalbox() to accept a list of
> levers to add to it. Do all that in the Trainset code. That's what
> it's for.
I hope you're getting my drift by now. I'm wondering about
boxes being instances of Trainset::Box::Lever instead, like this:
{
my $box = new Trainset::Box('Grosmont');
my $lever = new Trainset::Box::Lever('GS1');
$box->add($lever);
$tset->add($box);
}
or, with additional methods:
my $box = $tset->add_box('Grosmont');
$box->add_lever('GS1');
> > # would be nice if I could replace the above with a shortcut like
> >
> > # $box=$tset->add_signalbox('Grosmont'); # create signalbox
> > # $lever=$box->add_lever('GS1',0); # create lever and put in s'box
> Yes it would, but think bigger on the simplification scale. Maybe you
> even leave all these low-level methods in place as there may be a time
> when I need them, but give me a high-level interface that makes my life
> easier most of the time.
Wow! Didn't I just write that? You're catching on!
> > $lever->set_use(0,$points,'TCB2'); # position 0 = select TCB2
> > $lever->set_use(1,$points,'S1'); # position 1 = select S1
> >
> > $lever->throw(0); # throw lever
Or, so that it looks cute, use the alternative syntax:
throw $lever;
> > I hope that this has shown (a) what I am hoping to aim for with this
> > project
> > and (b) that I've taken on board the comments and hopefully
> > implemented the
> > suggestions correctly.
Yep. I think we're on a roll here.
> > Now the new questions.
> >
> > 1) I've put:
> >
> > use base (Trainset::Trains Trainset::Track Trainset::Signals
> > Trainset::Levers Trainset::Boxes);
> >
> > inside Trainset.pm. Is this the correct way to call in the other
> > classes?
>
> No it's not.
>
> use Trainset::Trains;
> use Trainset::Track;
> use Trainset::Signals;
> use Trainset::Levers;
> use Trainset::Boxes;
Yes it is (sorry James). 'use' on it's own doesn't build the object
dependencies. 'use base' is the right way to go, although I prefer
our @ISA; # read 'is a'
@ISA = qw/
Trainset::Train
Trainset::Track
Trainset::Signal
Trainset::Box
Trainset::Box::Lever
/;
> > If so, would this also give Trainset::Boxes access to
> > Trainset::Levers::add_lever to enable the shortcut I mentioned above?
>
> After you switch to the code above sure, but I'm not sure it needs to.
> Trainset is the glue object. Use it that way. Trainsets'
> add_signalbox() should create the box, create the lever(s) and link
> them together. Trainset::Boxes just needs to worry about itself, in
> construction at least.
I'm not sure what you mean here. All code has access to something
fully-qualified like Trainset::Levers::add_lever, but you must
restrict youself to /either/ class/object syntax
my $lever = $box->add_lever('GS1');
/or/ package syntax
my $lever = Trainset::Box::Lever::new('GS1');
but don't use package syntax if you're writing OO!
> > 2) What I do with the data will obviously depend on the program using
> > my
> > object, but would probably be things like update the screen (Term, TK,
> > Win32), or to send instructions to a control system (e.g. throw points
> > on
> > model railway).
> >
> > What is the best method to pass control back to the program from
> > within a
> > method?
>
> I don't think I understand this question. The obvious answer to me is
> return (exit the method). Control will pass back to the caller at this
> point, as it always does. If I misunderstood, please try explaining it
> again.
'return' :)
but, like James, I'm not sure what you mean. You seem to have a
number of preconceptions about how the software is to work that aren't
necessarily true. I hope we've banished DESTROY methods, but this
looks like you're expecting callbacks as well? Try to step through
a description of what you mean.
And again, don't lose heart: you've set up a huge target for yourself
and progressed a lot towards it.
Cheers,
Rob
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>