Class interfaces with implementations (like "modules" in Ruby)

liunx

Guest
I'm a Rubyist who has found himself doing an app in PHP. There's a specific bit of functionality that I miss from Ruby, and I'm searching for a way to replicate it. Here's the general situation:

I have several classes (all extending one class, an implementation of the Active Record design pattern) that all have a common set of functionality. Obviously, an interface would make sense. So, for example:


abstract class ActiveRecord
{
# ..
}

interface Departmental
{
# Related getters and setters
public function find_by_department($department);
}

class Priority extends ActiveRecord implements Departmental
{
# ...
public function find_by_department($department)
{
# Code that isn't specific to this class
}
}

class Coordinator extends ActiveRecord implements Departmental
{
# ...
public function find_by_department($department)
{
# Code that isn't specific to this class
}
}

# ... more that implement Departmental


The problem is that the code for the method(s) in Departmental doesn't vary with what class I'm using. However, the code isn't applicable to every class that extends ActiveRecord, so it can't go there. The best that PHP seems to be able to do is apply that interface. (Which, really, is all an interface is supposed to do, I suppose.) Then, I copy and paste the code that's in common. That's less than ideal, obviously.

Here's how the problem would be solved in Ruby


# Ruby doesn't have abstract classes, but can do abstract methods, etc
class ActiveRecord
# ...
end

module Departmental
# ...
def find_by_department(department)
# Code that's usable in any of the classes in which it's "mixed in"
end
end

class Priority < ActiveRecord
include Departmental # includes everything that's in Departmental, implementations and all
# ...
end

class Coordinator < ActiveRecord
include Departmental
# ...
end


This strategy is much more flexible. Here I only have to change code one place, and it propogates to every class that "includes" the mixin.

So, is there a way to replicate this in PHP? One of my first hopes was the following:

file: departmental.php

public function find_by_department($department)
{
# ...
}


file: priority.php

class Priority extends ActiveRecord
{
include 'departmental.php';
# ...
}


... which might have worked if PHP's "include" was more like a preprocessing directive, as in C/C++.

Any ideas? I really don't want to have to copy and paste code to do something that's so simple.I can't think of a simple solution. One possibility might be an extra layer of class extension:

abstract class A
{
// common variables and methods
}

abstract class B extends A
{
// add additional variables and methods
}

class C extends A
{
// only has basic stuff
}

class D extends B
{
// has both basic and additional stuff
}I had attempted that type of solution for a bit, but it quickly gets "hairier" than I would like. Unfortunately, it may be the way I have to go.You will probably want to create a DepartmentImplementation class and then redirect your method calls to it:

class whatever implements Depatrmental
{
function find_by_department($department)
{
return (new DepartmentalImplementation)->find_by_department($department));
}
}

That minimizes your cutting and pasting while retaining the advantages of using interfaces.I agree with ahundiak here - seems like Strategy to me.
 
Back
Top