Kann ich eine Methode in einem Objekt sowohl als statische als auch als nicht statische Methode mit demselben Namen deklarieren, der die statische Methode aufruft?
Ich möchte eine Klasse erstellen, die eine statische Methode "send" und eine nicht statische Methode hat, die die statische Funktion aufruft. Zum Beispiel:
class test {
private $text;
public static function instance() {
return new test();
}
public function setText($text) {
$this->text = $text;
return $this;
}
public function send() {
self::send($this->text);
}
public static function send($text) {
// send something
}
}
Ich möchte in der Lage sein, die Funktion auf diesen beiden aufzurufen
test::send("Hello World!");
und
test::instance()->setText("Hello World")->send();
ist es möglich?
Antworten:
Sie können dies tun, aber es ist ein bisschen schwierig. Sie müssen es mit Überladung tun: die
__call
und__callStatic
magische Methoden.class test { private $text; public static function instance() { return new test(); } public function setText($text) { $this->text = $text; return $this; } public function sendObject() { self::send($this->text); } public static function sendText($text) { // send something } public function __call($name, $arguments) { if ($name === 'send') { call_user_func(array($this, 'sendObject')); } } public static function __callStatic($name, $arguments) { if ($name === 'send') { call_user_func(array('test', 'sendText'), $arguments[0]); } } }
Dies ist keine ideale Lösung, da es schwieriger ist, Ihrem Code zu folgen, aber es funktioniert, vorausgesetzt, Sie haben PHP> = 5.3.
quelle
Nein, Sie können nicht zwei Methoden mit demselben Namen haben. Sie können im Grunde das Gleiche tun, indem Sie eine der Methoden umbenennen. Umbenennen
test::send("Hello World!");
intest::sendMessage("Hello World!");
würde funktionieren. Ich würde nur eine einzelne Sendemethode mit einem optionalen Textargument erstellen, das die Funktionsweise der Methode ändert.public function send($text = false) { if (!$text) { $text = $this -> text; } // Send something }
Ich bin gespannt, warum Sie die statische Funktion überhaupt brauchen.
quelle
Ich würde eine versteckte Klasse als Konstruktor erstellen und diese versteckte Klasse innerhalb der übergeordneten Klasse zurückgeben, deren statische Methoden den Methoden der versteckten Klasse entsprechen:
// Parent class class Hook { protected static $hooks = []; public function __construct() { return new __Hook(); } public static function on($event, $fn) { self::$hooks[$event][] = $fn; } } // Hidden class class __Hook { protected $hooks = []; public function on($event, $fn) { $this->hooks[$event][] = $fn; } }
Um es statisch zu nennen:
Hook::on("click", function() {});
Um es dynamisch zu nennen:
$hook = new Hook; $hook->on("click", function() {});
quelle
Ich bin damit einverstanden, dass dies um jeden Preis vermieden werden sollte, aber es gibt einige Fälle, in denen es nützlich sein könnte.
In den meisten Fällen wird Ihr Code nur unlesbar und nicht verwaltbar.
Glauben Sie mir, ich bin diesen Weg gegangen.
Hier ist ein Beispiel mit einem Anwendungsszenario, in dem es möglicherweise noch praktikabel ist.
Ich erweitere die Dateiklasse von CakePHP 3.0 als meine Standardklasse für die Dateiverwaltung.
Ich wollte einen statischen Mime-Guesser einsetzen.
In einigen Fällen habe ich einen Dateinamen anstelle einer tatsächlichen Datei, und in diesem Fall müssen einige Annahmen getroffen werden. (Wenn die Datei vorhanden ist, versuchen Sie, die MIME daraus abzurufen. Andernfalls verwenden Sie die Erweiterung des angegebenen Dateinamens.)
In anderen Fällen sollte die Standardmethode mime () funktionieren, wenn ich ein Objekt tatsächlich instanziiert habe. Wenn dies jedoch fehlschlägt, muss der Dateiname aus dem Objekt extrahiert und stattdessen die statische Methode aufgerufen werden.
Um Verwirrung zu vermeiden, war es mein Ziel, den MIME-Typ durch Aufrufen derselben Methode zu ermitteln:
Statisch:
NS\File::type('path/to/file.txt')
Als Objekt
$f = new NS\File('path/to/file.txt'); $f->type();
Hier ist mein Beispiel für eine erweiterte Klasse:
<?php namespace NS; class File extends \Cake\Utility\File { public function __call($method, $args) { return call_user_func_array([get_called_class(), 'obj'.ucfirst($method)], $args); } public static function __callStatic($method, $args) { return call_user_func_array([get_called_class(), 'static'.ucfirst($method)], $args); } public function objType($filename=null){ $mime = false; if(!$filename){ $mime = $this->mime(); $filename = $this->path; } if(!$mime){ $mime = static::getMime($filename); } return $mime; } public static function staticType($filename=null){ return static::getMime($filename); } public static function getMime($filename = null) { $mimes = [ 'txt' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', 'php' => 'text/html', 'ctp' => 'text/html', 'twig' => 'text/html', 'css' => 'text/css', 'js' => 'application/javascript', 'json' => 'application/json', 'xml' => 'application/xml', 'swf' => 'application/x-shockwave-flash', 'flv' => 'video/x-flv', // images 'png' => 'image/png', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'bmp' => 'image/bmp', 'ico' => 'image/vnd.microsoft.icon', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', // archives 'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed', 'exe' => 'application/x-msdownload', 'msi' => 'application/x-msdownload', 'cab' => 'application/vnd.ms-cab-compressed', // audio/video 'mp3' => 'audio/mpeg', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', // adobe 'pdf' => 'application/pdf', 'psd' => 'image/vnd.adobe.photoshop', 'ai' => 'application/postscript', 'eps' => 'application/postscript', 'ps' => 'application/postscript', // ms office 'doc' => 'application/msword', 'rtf' => 'application/rtf', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', // open office 'odt' => 'application/vnd.oasis.opendocument.text', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', ]; $e = explode('.', $filename); $ext = strtolower(array_pop($e)); if (array_key_exists($ext, $mimes)) { $mime = $mimes[$ext]; } elseif (function_exists('finfo_open') && is_file($filename)) { $finfo = finfo_open(FILEINFO_MIME); $mime = finfo_file($finfo, $filename); finfo_close($finfo); } else { $mime = 'application/octet-stream'; } return $mime; } }
quelle
Es tut mir leid, dass ich einen alten Thread gestoßen habe, aber ich möchte die Antwort von @lonesomeday erweitern. (Danke @lonesomeday für das erste Codebeispiel.)
Ich habe auch damit experimentiert, wollte aber die Methoden nicht so aufrufen, wie er sie im ursprünglichen Beitrag genannt hat. Stattdessen habe ich folgendes, was zu funktionieren scheint :
class Emailer { private $recipient; public function to( $recipient ) { $this->recipient = $recipient; return $this; } public function sendNonStatic() { self::mailer( $this->recipient ); } public static function sendStatic( $recipient ) { self::mailer( $recipient ); } public function __call( $name, $arguments ) { if ( $name === 'send' ) { call_user_func( array( $this, 'sendNonStatic' ) ); } } public static function mailer( $recipient ) { // send() echo $recipient . '<br>'; } public static function __callStatic( $name, $arguments ) { if ( $name === 'send' ) { call_user_func( array( 'Emailer', 'sendStatic' ), $arguments[0] ); } } } Emailer::send( '[email protected]' ); $Emailer = new Emailer; $Emailer->to( '[email protected]' ); $Emailer->send();
quelle