2021/05/28/a kluge using abstract methods: Difference between revisions
Jump to navigation
Jump to search
(Created page with "{{box/nav/log}} category:post category:ferreteria 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 underlyin...") |
mNo edit summary |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{ | {{nav/codeblog}} | ||
[[category:post]] | [[category:post]] | ||
[[category: | [[category:PHP 7.4]] | ||
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 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. | * I have a number of [https://php.net/trait 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. | * 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... | ** 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... | ||
Line 12: | Line 12: | ||
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. | 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== | |||
<syntaxhighlight lang=php> | |||
/*:::: | |||
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; | |||
} | |||
</syntaxhighlight> |
Latest revision as of 00:07, 2 July 2022
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;
}