Interfaces
Closed this issue · 6 comments
In most OO languages you have "interfaces".
DBI is the DataBase Interface on CPAN but not a really interface. But it could be.
An interface is something like a role with only abstract methods and it is not possible to create instances of interfaces.
Or you can say: an interface is a abstract role.
You can derive interfaces like roles and classes.
An interface defines methods, that can be called on an object and the programmers use interfaces instead of classes like this:
interface IEnumeration {
method entries();
method add($str);
}
interface IList isa IEnumeration {
method count();
}
class List implements IList {
has @list_entries;
method entries() {
return @list_entries;
}
method add($str) {
push @list_entries, $str;
}
method count() {
return scalar @list_entries;
}
}
my $list is IList = List->new;
$list->add("a String value");
foreach my $l ($list->entries) {
say $l;
}
$list->count(); # error, because count is no method of interface IEnumeration
With interfaces, it is possible to create a DB-access-factory like this:
my $dbi_read = $DBI->database_accessor_readonly("Server", "MyDatabase");
foreach my $row ($dbi_read->query(...)) {
say $row->print();
}
and you cannot call Insert(), Update() or Delete() on $dbi_read, because database_accessor_readonly() returns interface IDbRead.
my $dbi_rw = $DBI->database_accessor_rw("Server", "MyDatabase");
can do Query() and Update(), because it returns IDbReadWrite.
my $dbi = $DBI->database_accessor_full("Server", "MyDatabase");
can do Query(), Insert(), Update() and Delete(), because it returns IDbFullRowAccess;
But it cannot create oder drop tables.
interface IDbRead {
method Query(...);
}
interface IDbReadWrite isa IDbRead {
method Update(...);
}
interface IDbFullRowAccess isa IDbReadWrite {
method Insert(...);
method Delete(...);
}
And everything is implemented in the same class DBI::MySql:
class DBI::MySql implements IDbFullRowAccess {
method Query(...);
method Update(...);
method Insert(...);
method Delete(...);
}
We have interfaces. They are simply roles without default implementations. The only question is whether or not we'll use requires
or abstract
:
role IDbFullRowAccess {
requires qw(
query
update
insert
delete
);
}
versus:
role IDbFullRowAccess {
abstract method query (...);
abstract method update (...);
abstract method insert (...);
abstract method delete (...);
}
Oops. Closed this by accident. I'll close it again later unless someone points out some flaw in the Corinna approach.
I prefer "abstract". This is needed for methods with different signatures, but same name.
Recent discussions wondered if we even need the abstract
word at all; whether just giving a prototype with no definition is sufficient:
role Bouncable {
method bounce($height);
}
@leonerd I think you're right that a method forward declaration would be sufficient. However, if we're to allow abstract classes, we would have to have that on the class declaration. Using the example from my last talk:
abstract class Boolean {
method ifTrue ($code) {}
method ifFalse ($code) {}
}
Here we must declare the class as abstract because it must not be instantiated directly, even though it doesn't have any abstract methods.
This is resolved for the MVP. Further issues should be new tickets.