Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Inherit from a Role (or something like that)

by elTriberium (Friar)
on May 20, 2011 at 19:48 UTC ( [id://905958]=perlquestion: print w/replies, xml ) Need Help??

elTriberium has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I'm still struggling a bit with the Moose concept of Roles. I'm trying to solve a specific problem here, but can't figure out how to do it with Moose.

In this project we have a Role "RemoteConnection" which is added to 2 modules: "SSH" and "Socket" to provide access to remote resources. Based on a configuration option we want to chose during runtime whether we're using an SSH or Socket connection.

We also have multiple derived modules, e.g. "Server" and "Client" that. I want to write those modules only against the interface defined in the RemoteConnection role, so that I can easily exchange SSH by Socket and vice-versa whenever needed. The application will then create a Server or Client object and will be able to run stuff on that resource without having to care whether this is an SSH or Socket connection. I already defined the role and this is added into the 2 modules, but now how do I write my other classes against this role?

I thought about a few solutions, but none fulfils all the requirements: I thought about using a factory which creates either a SSH or Socket object, but then I can't easily inherit from both of them in Server and Client.

Inheritance is needed because the child classes have to overwrite some attributes and methods of the parent class(es).

  • Comment on Inherit from a Role (or something like that)

Replies are listed 'Best First'.
Re: Inherit from a Role (or something like that)
by John M. Dlugosz (Monsignor) on May 20, 2011 at 20:07 UTC
    Have you read the original "traits" paper?

    but now how do I write my other classes against this role?
    Other code should be written to use only the API provided by the RemoteConnection role, without caring what class it is otherwise. Any type checking should use the role name.

    but then I can't easily inherit from both of them in Server and Client.
    That sounds like a different problem. Maybe you didn't explain it well? Are you saying that Server and Client each want a different derived class of the Connection, but the Connection may already be different concrete classes?

    You need to aggregate rather than further derive. Have the Connection class that you will be deriving from contain a SSH or Socket back-end instance, rather than being derived from it.

    In fact, you might not need inheritance in the other place, either. Look at using collaborating instances instead. You can use delegation to make the result just as slick as inheritance rather than having to forward everything all over the place. Delegation can easily behave like inheritance from a run-time specified instance.

    See this node for more recent discussion on delegation.

      Thanks, the other node you're referring to was an answer to my previous question :)
      Are you saying that Server and Client each want a different derived class of the Connection, but the Connection may already be different concrete classes?
      I'm not sure if I understand you here correctly: The basic idea is to have 2 interchangeable ways of providing "remote access" functionality to the Server and Client objects. The application will then do something like:
      my $server = Server->new(type => "ssh"); # to create an SSH connection $server->run("ifconfig"); my $server2 = Server->new(type => "socket"); # to create a socket conn +ection $server2->run("ifconfig"); my $client = Client->new(type => "ssh"); $client->run("ls");
      Where in this example "run" is defined in the Role and implemented by SSH and Socket.
        So Server and Client are both different from each other (though may share some stuff), and SSH and Socket are also different from each other but share a common interface.

        So, Server and Client (or their base class) "has" (not "is"!) a Connection. A Connection may be different concrete classes, or may be a single class that "has" a BackEnd. Note that in Perl you are more flexible in not having to define an "Interface" or have explicit base/derived relationships. Each concrete class can be implemented in any way it likes.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://905958]
Approved by John M. Dlugosz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-04-25 23:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found