클래스 내에서 정적 메소드를 호출합니까?


166

같은 클래스 내의 다른 메소드에서 정적 메소드를 어떻게 호출합니까?

$this->staticMethod();

또는

$this::staticMethod();

13
당신이 (에 관심이있을 수 self$this) : stackoverflow.com/questions/151969/php-self-vs-this
펠릭스 클링

참고로, 첫 번째 예는 정적 메서드를 호출하는 인스턴스 변수입니다. 정적 메서드는 클래스의 일부이며 인스턴스 변수를 통해 액세스 할 수 없기 때문에 불가능합니다.
joejoeson

정적 메소드 만 사용하고 인스턴스가없는 경우 $ this를 삭제할 수 있습니다.
malhal

답변:


321

...하지만 왜? $ this-> staticMethod ()도 작동합니다. self :: staticMethod ()가 더 정확한 이유를 설명 할 수 있습니까?
Ian Dunn

29
@Ian Dunn Put은 단순히 $this객체가 인스턴스화되고 $this->method기존 객체 내 에서만 사용할 수있는 경우에만 존재합니다. 객체가 없지만 정적 메소드를 호출하고 해당 메소드에서 동일한 클래스의 다른 정적 메소드를 호출하려면을 사용해야 self::합니다. 따라서 잠재적 인 오류 (및 엄격한 경고)를 피하려면 사용하는 것이 좋습니다 self.
jeroen

1
감사! laravel에서 실수로을 사용하여 확장 컨트롤러에서 정적 메소드를 호출하고 있음을 발견 $this했지만 코드가로 푸시 될 때까지 문제가 발생하지 않았습니다 stage. 오류가 다시 발생하지 않았습니다 0. 값은 단지 입니다. 이것을 조심하십시오self::
blamb

44

이것이 당신의 수업이라고 가정 해 봅시다.

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

    public static function staticMethod() { echo "static method\n"; }
}

foo()방법 내 에서 다른 옵션을 살펴 보겠습니다.

$this->staticMethod();

staticMethod()인스턴스 메소드로 호출 하는 것이 맞습니까? 그렇지 않습니다. public static인터프리터가 정적 메소드로 호출 할 때 메소드가 선언 되었으므로 예상대로 작동합니다. 그렇게하면 정적 메소드 호출이 발생하고 있음을 코드에서 덜 명확하게 할 수 있다고 주장 할 수 있습니다.

$this::staticMethod();

PHP 5.3부터는 다음 $var::method()을 의미 할 수 있습니다 <class-of-$var>::. 위의 사용 사례는 여전히 전통적이지 않지만 이것은 매우 편리합니다. 따라서 정적 메소드를 호출하는 가장 일반적인 방법이 있습니다.

self::staticMethod();

당신은이 생각을 시작하기 전에 지금 ::이다 정적 호출 연산자는, 내가 당신에게 또 다른 예를 해주지 :

self::bar();

이것은 인쇄 할 수 baz = 1있는 수단이, $this->bar()그리고 self::bar()정확히 같은 일을 할; 그것은 ::단지 범위 확인 연산자 이기 때문 입니다. 그것은이 만드는의 parent::, self::그리고 static::작업하고 정적 변수에 대한 액세스를 제공을; 메소드의 호출 방법은 서명 및 호출자의 호출 방법에 따라 다릅니다.

이 모든 것을 실제로 보려면 이 3v4l.org 출력을 참조하십시오 .


self::bar()오해의 소지가있는 것 같습니다. 이제 더 이상 사용되지 않습니까? ( self::정적 메소드가 아닌 인스턴스 메소드를 호출하는 데 사용 ).
ToolmakerSteve

@ToolmakerSteve 오해의 소지가 있다고 어떻게 말 하시겠습니까?
Ja͢ck

논리적으로 말하면 self정적 메서드를 호출 할 때는 없습니다 . 정의 : 정적 메소드는 어디에서나 호출 가능하며 "self"매개 변수를받지 않습니다. 그럼에도 불구하고, 나는 그 php구문 의 편리함을 알고 있으므로 쓸 필요가 없습니다 MyClassName::. 저는 정적 타입 언어에 익숙합니다. 컴파일러는 현재 범위에서 사용 가능한 모든 변수를 제공해야하므로 (동등한) self::생략 할 수 있습니다. 그래서 하나만 말했다 self instanceMethod; 말할 이유가 없습니다 self staticMethod.
ToolmakerSteve

15

이것은 매우 늦은 답변이지만 이전 답변에 대한 세부 정보를 추가합니다

동일한 클래스의 다른 정적 메소드에서 PHP의 정적 메소드를 호출하는 self경우 클래스 이름 을 구별하는 것이 중요합니다 .

이 코드를 예로 들어 보겠습니다.

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

이 코드의 출력은 다음과 같습니다.

오리지널 클래스

확장 수업

self호출되는 코드의 클래스가 아니라 코드가있는 클래스를 참조하기 때문 입니다.

원래 클래스를 상속하는 클래스에 정의 된 메소드를 사용하려면 다음과 같은 것을 사용해야합니다.

$class = get_called_class();
$class::function_name(); 

2
이 정보를 찾았습니다. 작은 니트, 나는 다른 답변이 "오해의 소지가 없다"고 말하지 않을 것입니다. 그들이 "불완전하다"고 말하는 것이 더 정확합니다. self::정적 메소드 A가 다른 정적 메소드 B를 호출하고 서브 클래스에서 B가 대체 된 (희귀 한) 경우에 수행되는 문제에 대한 (미확정) 질문은 다루지 않습니다. IMHO, 메소드 재정의를 "인스턴스"메소드로 제한하는 것은 덜 혼란 스럽습니다. 정적 레벨에서 그 능력을 조금만 사용하십시오. 다시 말해, 코드 독자는 인스턴스 메소드 (OO 코딩의 본질)를 대체하는 메소드를 기대하지만 정적 메소드는 그렇지 않습니다.
ToolmakerSteve

1
매우 유용하며 클래스의 확장이 원래 클래스가 아님을 의미합니다. 따라서이 self경우에는 사용되지 않는 이유가 있습니다. 첫 번째 클래스의 확장으로 별도의 클래스를 선언했습니다. self확장 클래스 내에서 사용 하는 것은 확장 클래스를 나타냅니다. 이것은 다른 답변과 모순되지 않지만의 범위를 분명히 보여줍니다 self.
iyrin

2

이후의 PHP 버전 self::staticMethod();에서도 작동하지 않습니다. 엄격한 표준 오류가 발생합니다.

이 경우 같은 클래스의 객체를 생성하고 객체별로 호출 할 수 있습니다

여기에 예가 있습니다

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}

당신은 할 수 있다면하지만, 그렇게 fun1의 사용을하지 않습니다 self, 인스턴스 메서드 만들기 위해 논리적 없습니다. PHP에서이를 수행하는 올바른 방법은을 선언 public static function fun1하고 클래스를 지정하여 호출하는 것 Foo::fun1입니다. 나는 그것이 엄격한 표준 오류를 해결하기위한 의도 된 방법이라고 확신합니다.
ToolmakerSteve
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.