2009-09-09 10 views
89

Co chciałbym zrobić coś takiego:Czy w PHP można utworzyć instancję obiektu i wywołać metodę w tej samej linii?

$method_result = new Obj()->method(); 

Zamiast robić:

$obj = new Obj(); 
$method_result = $obj->method(); 

Wynik faktycznie nie ma dla mnie znaczenia w moim konkretnym przypadku. Ale czy jest jakiś sposób na zrobienie tego?

+3

btw, jeśli nie używasz 5.4 (co prawdopodobnie nie jest), możesz zdefiniować funkcję pomocniczą, która właśnie zwraca obiekt, aby połączyć łańcuch ... funkcja z ($ obj) {return $ obj; } (podniosła sztuczkę z laravel: P) .. wtedy możesz zrobić (nowy Obj) -> method() – kapv89

+0

Tak prosty jak '(nowy obiekt()) -> doSomething()'. –

Odpowiedz

117

Funkcja, o którą prosiłeś, dostępna jest w PHP 5.4. Oto lista nowych funkcji w PHP 5.4:

http://docs.php.net/manual/en/migration54.new-features.php

oraz odpowiedniej części z nowej listy cech:

dostęp członkiem klasy na instancji została dodana, na przykład (nowy Foo) -> bar().

+7

Zauważ, że oznacza to również, że możesz zrobić "(nowe Foo) -> właściwość', jeśli chcesz. – dave1010

+0

To jest naprawdę fajna funkcja PHP 5.4, szkoda, że ​​nie jest dostępna w wersji 5.3.27 (na której jestem). – crmpicco

+1

Należy pamiętać, że nie można jeszcze przypisać właściwości w ten sposób. (nowy Foo) -> właściwość = "właściwość"; – CMCDragonkai

14

Nie, nie jest to możliwe.
Musisz przypisać instancję do zmiennej, zanim będziesz mógł wywołać którąś z jej metod.

Jeśli naprawdę wa to zrobić można użyć fabrykę jako ropstah proponuje:

class ObjFactory{ 
    public static function newObj(){ 
     return new Obj(); 
    } 
} 
ObjFactory::newObj()->method(); 
+3

Odpowiedź Pima jest poprawna. Ewentualnie możesz użyć funkcji statycznych, jeśli nie chcesz tworzyć instancji obiektu – Mark

+1

Co to jest funkcja objFacotry?;) – Ropstah

6

Można użyć metody statycznej fabryki do produkcji obiektu:

ObjectFactory::NewObj()->method(); 
+2

Nie ma potrzeby posiadania oddzielnej fabryki; statyczna metoda w tej samej klasie osiągnie to samo. – Brilliand

18

Jak o :

$obj = new Obj(); $method_result = $obj->method(); // ? 

: P

+11

Świetna odpowiedź: P Zmusiła mnie do śmiechu. –

36

Nie możesz zrobić tego, o co prosisz; ale możesz "oszukiwać", wykorzystując fakt, że w PHP możesz mieć funkcję, która ma taką samą nazwę jak klasa; te nazwy nie będą w konflikcie.

Tak więc, jeśli zadeklarowana klasę tak:

class Test { 
    public function __construct($param) { 
     $this->_var = $param; 
    } 
    public function myMethod() { 
     return $this->_var * 2; 
    } 
    protected $_var; 
} 

Następnie można zadeklarować funkcję, która zwraca instancję tej klasy - i ma dokładnie taką samą nazwę jak klasa:

function Test($param) { 
    return new Test($param); 
} 

a teraz staje się możliwe użycie jednego-liner, jak prosiłeś - Jedyną rzeczą jest dzwonisz funkcji, więc nie za pomocą nowego:

$a = Test(10)->myMethod(); 
var_dump($a); 

I to działa: tu dostaję:

int 20 

jako wyjście.


I lepiej, można umieścić kilka PHPDoc na funkcję:

/** 
* @return Test 
*/ 
function Test($param) { 
    return new Test($param); 
} 

W ten sposób będziesz mieć nawet podpowiedzi w swoim IDE - przynajmniej z Eclipse PDT 2.x; zobacz screeshot:

http://extern.pascal-martin.fr/so/class-and-function.png



Edit 2010-11-30: Tylko dla informacji, nowy RFC został złożony kilka dni temu, że proponuje dodanie ta funkcja do jednej z przyszłych wersji PHP.

Patrz: Request for Comments: Instance and method call/property access

Więc może robić takie rzeczy jak to będzie możliwe w PHP 5.4 lub innej przyszłej wersji:

(new foo())->bar() 
(new $foo())->bar 
(new $bar->y)->x 
(new foo)[0] 
+0

nice! nie wiedziałem, że – knittl

+0

Ja też nie, dzięki. – Ropstah

+0

Wow, bardzo miło! Nie wiedziałem o tym. –

18

można to zrobić bardziej uniwersalnie definiując funkcję tożsamości:

function identity($x) { 
    return $x; 
} 

identity(new Obj)->method(); 

W ten sposób nie trzeba definiować funkcji dla każdej klasy.

+10

Ładne rozwiązanie, ponieważ podkreśla głupotę tego ograniczenia :) – Ole

3

Ja również szukałem jednego linijki, aby osiągnąć to jako część pojedynczego wyrażenia do konwersji dat z jednego formatu na inny. Lubię robić to w jednym wierszu kodu, ponieważ jest to jedna logiczna operacja. Tak, to jest trochę tajemniczy, ale pozwala instancji i używać obiektu daty w jednej linii:

$newDateString = ($d = new DateTime('2011-08-30') ? $d->format('F d, Y') : ''); 

Innym sposobem na jednej linijce konwersja łańcuchach daty z jednego formatu do drugiego jest użycie funkcja pomocnika do zarządzania części OO kodu:

function convertDate($oldDateString,$newDateFormatString) { 
    $d = new DateTime($oldDateString); 
    return $d->format($newDateFormatString); 
} 

$myNewDate = convertDate($myOldDate,'F d, Y'); 

Myślę, że podejście obiektowe jest cool i konieczne, ale może być czasami uciążliwe, wymagające zbyt wielu czynności, aby wykonać proste operacje.

0

widzę ten jest dość stary, jak pytania iść, ale tutaj jest coś myślę, że powinno być wymienione:

Specjalna metoda klasy o nazwie „__call()” może być wykorzystywane do tworzenia nowych przedmiotów wewnątrz klasy . Go używać tak:

<?php 
class test 
{ 

function __call($func,$args) 
{ 
    echo "I am here - $func\n"; 
} 

} 

    $a = new test(); 
    $a->new("My new class"); 
?> 

wyjściowe powinny być:

I am here - new 

sposób można oszukać PHP do tworzenia „nowego” polecenie wewnątrz swojej najwyższej klasy poziomu (lub każda klasa naprawdę) i umieść polecenie include w funkcji __call(), aby dołączyć klasę, o którą prosiłeś. Oczywiście prawdopodobnie będziesz chciał przetestować $ func, aby upewnić się, że jest to "nowe" polecenie, które zostało wysłane do polecenia __call() i (oczywiście) możesz mieć inne polecenia także z powodu działania funkcji __call().

Powiązane problemy