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();
가능할까요?
당신은 할 수 있습니다 이 작업을 수행하지만, 조금 까다로운. 오버로딩으로해야합니다 : the __call
and__callStatic
magic 메서드.
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 인 경우 작동합니다.
아니요 같은 이름을 가진 두 가지 방법을 가질 수 없습니다. 메서드 중 하나의 이름을 변경하여 기본적으로 동일한 작업을 수행 할 수 있습니다. 로 이름 test::send("Hello World!");
을 바꾸면 test::sendMessage("Hello World!");
작동합니다. 메서드가 작동하는 방식을 변경하는 선택적 텍스트 인수를 사용하여 단일 전송 메서드를 생성합니다.
public function send($text = false) {
if (!$text) {
$text = $this -> text;
}
// Send something
}
정적 함수가 왜 필요한지 궁금합니다.
숨겨진 클래스를 생성자로 만들고 숨겨진 클래스 메서드와 동일한 정적 메서드가있는 부모 클래스 내부에 숨겨진 클래스를 반환합니다.
// 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() {});
동적으로 호출하려면 :
$hook = new Hook;
$hook->on("click", function() {});
오래된 스레드를 부딪쳐서 죄송하지만 @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( 'foo@foo.foo' );
$Emailer = new Emailer;
$Emailer->to( 'bar@bar.bar' );
$Emailer->send();
나는 이것이 어떤 대가를 치르더라도 피해야한다는 데 동의하지만 유용 할 수있는 경우가 있습니다.
대부분의 경우 코드를 읽을 수없고 관리 할 수 없게됩니다.
저를 믿으십시오. 저는 그 길을 따라 왔습니다.
다음은 여전히 실용적 일 수있는 사용 사례 시나리오의 예입니다.
CakePHP 3.0의 File 클래스를 기본 파일 처리 클래스로 확장하고 있습니다.
나는 정적 MIME 유형 추측기를 넣고 싶었습니다.
어떤 경우에는 실제 파일 대신 파일 이름이 있으며이 경우 몇 가지 가정이 필요합니다. (파일이 존재하는 경우 MIME를 가져 오거나 제공된 파일 이름의 확장자를 사용하십시오)
실제로 객체를 인스턴스화 한 경우 기본 mime () 메서드가 작동해야하지만 실패하면 객체에서 파일 이름을 추출해야하고 대신 정적 메서드를 호출해야합니다.
혼동을 피하기 위해 내 목표는 동일한 메서드를 호출하여 MIME 유형을 가져 오는 것입니다.
공전:
NS\File::type('path/to/file.txt')
개체로
$f = new NS\File('path/to/file.txt');
$f->type();
다음은 내 예제 확장 클래스입니다.
<?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;
}
}
'Nice programing' 카테고리의 다른 글
크로스 브라우저 자바 스크립트 XML 파싱 (0) | 2020.11.28 |
---|---|
Java에서 임의의 BigInteger 값을 생성하는 방법은 무엇입니까? (0) | 2020.11.28 |
matplotlib 서브 플롯의 행 및 열 헤더 (0) | 2020.11.28 |
부동 소수점 수 구문 분석 : Catch All 알고리즘이 있습니까? (0) | 2020.11.28 |
1. # INF00, -1. # IND00 및 -1. # IND는 무엇을 의미합니까? (0) | 2020.11.28 |