2012-07-04 12 views
42

静的メソッドを呼び出すのと同じ名前の静的メソッドと非静的メソッドの両方としてオブジェクト内にメソッドを宣言できますか?PHP - 静的メソッドと非静的メソッドを宣言できますか?

私は静的メソッド "send"と静的関数を呼び出す非静的メソッドを持つクラスを作成したいと思います。例えば:私はこの二つに関数を呼び出すことができるようにしたい

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 
    } 
} 

はそれが可能

test::send("Hello World!"); 

test::instance()->setText("Hello World")->send(); 

ありましたか?

+4

私が聞いてもよければ、なぜそれをしたいですか? – PeeHaa

+0

[静的メンバーは非静的メンバーを使用することができますか?その逆もありますか?](0120-919-066) –

+0

答えはbtwではありません。しかし、私は本当にあなたがそれをしたいと思う理由について興味があります。 – PeeHaa

答えて

55

お客様ですが、これはややこしいことです。オーバーロードでそれをする必要があります:the __call and __callStatic魔法。

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 function __callStatic($name, $arguments) { 
     if ($name === 'send') { 
      call_user_func(array('test', 'sendText'), $arguments[0]); 
     } 
    } 
} 

あなたはPHP> = 5.3を持って、それは従って、あなたのコードは難しくなりますが、それは動作しますので、これは、理想的なソリューションではありません。

+24

これは私の目をb̢̗̫͕l͓̫͈e҉͍̖͙ḙ̣̭̦̫̞͟dmakesにします。この種のコーディングは人生を楽にしないと警告しているので、私はそれをダウンボケしません。しかしまだ:< –

+10

@lonesomedayあなたは目に見える用途がほとんどないコードを書くために忍耐力を持っているからだけ投票してください!それでも質問に答えます:-) –

+3

@Truthはい。 "これをすることができますが、***あなたは本当に***すべきではありません。" – lonesomeday

3

いいえ同じ名前のメソッドを2つ使用することはできません。これらのメソッドの名前を変更することで、基本的に同じことができます。 test::send("Hello World!");からtest::sendMessage("Hello World!");に名前を変更すると機能します。私はちょうどメソッドの機能を変更するオプションのテキスト引数を持つ単一のsendメソッドを作成します。

public function send($text = false) { 
    if (!$text) { 
     $text = $this -> text; 
    } 

    // Send something 
} 

なぜ静的機能が必要なのか、

+3

これを行うには、静的メソッドの名前を変更することは間違いありません。 – lonesomeday

-1

申し訳ありませんが古いスレッドをバンプしますが、@ lonesomedayの答えを広げたいと思います。 (初期のコードサンプルでは@lonesomedayになります)

私もこれも実験していましたが、元の投稿でメソッドを呼び出すときにメソッドを呼びたくありませんでした。代わりに、私は仕事にを思われる、次のようにしている:私は、これはすべてのコストで避けるべきであることに同意

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(); 
-1

それが役に立つかもしれないいくつかの例があります。

ほとんどの場合、コードを読むことができず、管理不能になるだけです。

私を信じて、私はその道を歩いています。

これはまだ実用的なユースケースシナリオの例です。

私はCakePHP 3.0のFileクラスを私のデフォルトのファイル処理クラスとして拡張しています。

私は静的なMIMEタイプの推測者を入れたいと思っていました。

場合によっては、実際のファイルではなくファイル名があります。この場合、いくつかの前提が必要です。(ファイルが存在する場合は、そこからmimeを取得してください)他の時に、実際にオブジェクトをインスタンス化すると、デフォルトのmime()メソッドが機能しますが、失敗した場合はファイル名を抽出する必要があります。代わりにオブジェクトから静的メソッドを呼び出す必要があります。

私の目的は同じメソッドを呼び出すことにより、MIMEタイプを取得することでした。混乱を避けるために、:

静的:オブジェクト

$f = new NS\File('path/to/file.txt'); 
$f->type(); 

として

NS\File::type('path/to/file.txt') 

ここれます私の例の拡張クラス:

<?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; 
    } 
} 
0

私はコンストラクタとして隠されたクラスを作成し、隠されたクラスメソッドに等しい静的メソッドを持つ親クラス内のその隠されたクラスを返すでしょう:静的に呼び出すには

// 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; 
    } 

} 

を:

Hook::on("click", function() {}); 

それを動的に呼び出すには:

0

もっと簡単な方法があります。

class MyClass { 

    private $r = "I'm regular!"; 

    private static $s = "I'm static!"; 

    public function method() { 
     if (isset($this) && $this instanceof self) { 
      // Regular call 
      echo $this->r; 
     } else { 
      // Static call 
      echo static::$s; 
     } 
    } 

} 

今、あなたは簡単に行うことができます

(new MyClass())->method(); 
// I'm regular! 

または

MyClass::method(); 
// I'm static! 

をあなたは問題の記述のすべてを達成するために、このフレームワークを使用することができます。

関連する問題