2021/05/28/a kluge using abstract methods
Jump to navigation
Jump to search
Template:Box/nav/log I don't know if I'll end up using this technique or not, but I thought I'd make a note of it because of the underlying problem it illustrates.
- I have a number of traits which need to be initialized somehow.
- It turns out to be a bad idea to define constructors inside traits, because the different classes that use those traits may have different constructor arguments.
- In other words, there's no clean way to have a trait call the constructor of a class that uses it, unless you carefully restrict what classes can use it...
- ...and even if that were desirable (which it is in some circumstances), there's no way to enforce it.
- In other words, there's no clean way to have a trait call the constructor of a class that uses it, unless you carefully restrict what classes can use it...
- I had resorted to putting notes in the trait documentation -- like "HOSTING: host must call [name_of_trait_initialization_method]"...
- ...but when a trait is several layers deep in other traits (which happens a lot with the method/routing pattern I use), this can be easy to overlook.
The solution I'm trying is to just define an abstract method named "Call_[name_of_initialization_method]". Whatever host does the calling simply defines this method with no code, to signal that the call has happened. This serves as nothing more than a reminder to the coder that a thing needs to be done when using a given trait.
Example
/*::::
HOSTING: Host must call CreatePortBank() before calling PortBank().
*/
trait tMaker {
use tUser;
abstract protected function Call_CreatePortbank(); // a reminder
protected function CreatePortBank() {
$sClass = $this->PortBankClass();
$os = $this->Space();
$op = $os->MakePiece($this->PortBankPieceName());
$of = new $sClass($os);
$op->SetIt($of);
}
abstract protected function PortBankClass() : string;
}