PHP'de, bir nesneyi başlatıp aynı satırda bir yöntemi çağırabilir misiniz?


126

Yapmak istediğim şey şöyle bir şey:

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

Yapmak zorunda kalmak yerine:

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

Benim özel durumumda sonuç benim için önemli değil. Ama bunu yapmanın bir yolu var mı?


4
btw, 5.4 kullanmıyorsanız (ki muhtemelen kullanmıyorsunuz), bir nesneyi zincirleme nesneye döndüren bir yardımcı işlev tanımlayabilirsiniz ... function ile ($ obj) {return $ obj; } (numarayı laravel'den aldı: P) .. sonra (new Obj) -> method ()
kapv89

BTW, eğer kendinizi bunu sık sık yaparken bulursanız, bunun my_methodyerine beyan edilmesi gerekip gerekmediğini düşünmeye değer static.
ToolmakerSteve

Yanıtlar:


167

İstediğiniz özellik PHP 5.4'ten itibaren mevcuttur. İşte PHP 5.4'teki yeni özelliklerin listesi:

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

Ve yeni özellikler listesinden ilgili kısım:

Örneklemede sınıf üyesi erişimi eklendi, örneğin (yeni Foo) -> bar ().


9
Bunun, isterseniz yapabileceğiniz anlamına da geldiğini unutmayın (new Foo)->property.
dave1010

1
Henüz bu şekilde özellikler atayamayacağınızı unutmayın. (yeni Foo) -> özellik = 'özellik';
CMCDragonkai

7
@CMCDragonkai mantıksal olarak bu mantıklı; nesne yalnızca ifadenin süresi boyunca var olur (new Foo)->property- sakladığınız değerin gidecek yeri yoktur çünkü nesne bundan sonra hiçbir yerde depolanmadığı için artık var olmayacaktır.
thomasrutter

1
@CMCDragonkai İlgili ayarlayıcıları arayarak özellikleri bu şekilde atayabilirsiniz , tek yapmanız gereken return $thisayarlayıcılarınıza eklemek . Bu ayrıca ayarlayıcıları zincirlemenize izin verecektir.
iloo

Bir sorum var. Nesneyi ayrı bir satırda bildirip bir değişkene kaydetmenin, nesneyi yeniden kullanabilmenin dışında bir faydası var mı?
Tyler Swartzenburg

37

İstediğini yapamazsın; fakat PHP'de sınıfla aynı ada sahip bir işleve sahip olabileceğiniz gerçeğini kullanarak "hile yapabilirsiniz"; bu isimler çelişmez.

Öyleyse, böyle bir sınıf ilan ettiyseniz:

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

Daha sonra, bu sınıfın bir örneğini döndüren ve sınıfla tam olarak aynı ada sahip bir işlev bildirebilirsiniz:

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

Ve şimdi, istediğiniz gibi tek satırlık kullanmak mümkün hale geliyor - tek şey işlevi çağırıyorsunuz, dolayısıyla yeniyi kullanmıyorsunuz:

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

Ve işe yarıyor: burada, alıyorum:

int 20

çıktı olarak.


Ve daha iyisi, işlevinize biraz phpdoc koyabilirsiniz:

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

Bu şekilde, IDE'nizde ipuçlarına bile sahip olacaksınız - en azından Eclipse PDT 2.x ile; ekran görüntüsüne bakın:



Düzenleme 2010-11-30: Sadece bilgi amaçlı olarak, birkaç gün önce bu özelliği PHP'nin gelecek sürümlerinden birine eklemeyi öneren yeni bir RFC gönderildi.

Bkz .: Yorum İsteği: Örnek ve yöntem çağrısı / özellik erişimi

Öyleyse, belki bunun gibi şeyler yapmak PHP 5.4 veya başka bir gelecek sürümde mümkün olabilir:

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

19

Bir kimlik işlevi tanımlayarak bunu daha evrensel olarak yapabilirsiniz:

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

identity(new Obj)->method();

Bu şekilde her sınıf için bir işlev tanımlamanıza gerek kalmaz.


10
Bu sınırlamanın aptallığını vurguladığı için güzel çözüm :)
Ole

19

Peki ya:

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

: P


16

Hayır, bu mümkün değil.
Yöntemlerinden herhangi birini çağırmadan önce örneği bir değişkene atamanız gerekir.

Bunu gerçekten yapmak istemiyorsanız, ropstah'ın önerdiği gibi bir fabrika kullanabilirsiniz:

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

4
Pim'in cevabı doğru. Alternatif olarak, nesnenin bir örneğini oluşturmak istemiyorsanız statik işlevleri kullanabilirsiniz
Mark

bunu kullanmak public static functionyerine kullanmaya zorlanıyoruz public function. Statik kullanılması tavsiye edilir mi?
ichimaru

6

Nesneyi üretmek için statik bir fabrika yöntemi kullanabilirsiniz:

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

3
Ayrı bir fabrikaya gerek yok; aynı sınıftaki statik bir yöntem aynı şeyi başaracaktır.
Brilliand

3

Ben de tarihleri ​​bir formattan diğerine dönüştürmek için tek bir ifadenin parçası olarak bunu başarmak için tek satırlık bir program arıyordum. Bunu tek bir kod satırında yapmayı seviyorum çünkü bu tek bir mantıksal işlem. Yani, bu biraz şifreli, ancak bir tarih nesnesini tek bir satırda başlatmanıza ve kullanmanıza izin verir:

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

Tarih dizelerinin bir biçimden diğerine tek satırlı dönüştürülmesinin başka bir yolu, kodun OO bölümlerini yönetmek için bir yardımcı işlev kullanmaktır:

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

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

Nesne yönelimli yaklaşımın havalı ve gerekli olduğunu düşünüyorum, ancak bazen sıkıcı olabilir ve basit işlemleri gerçekleştirmek için çok fazla adım gerektirebilir.


0

Bunun sorular oldukça eski olduğunu görüyorum ama burada belirtilmesi gerektiğini düşündüğüm bir şey var:

"__Call ()" adlı özel sınıf yöntemi, bir sınıfın içinde yeni öğeler oluşturmak için kullanılabilir. Bunu şöyle kullanırsın:

<?php
class test
{

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

}

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

Çıktı şöyle olmalıdır:

I am here - new

Böylece, PHP'yi üst düzey sınıfınızın (veya gerçekten herhangi bir sınıfın) içinde "yeni" bir komut oluşturması için kandırabilir ve dahil etme komutunuzu __call () işlevine, istediğiniz sınıfı dahil etmek için koyabilirsiniz. Tabii ki, __call () komutuna gönderilen "yeni" bir komut olduğundan emin olmak için muhtemelen $ func'ı test etmek istersiniz ve (tabii ki) __call () işlevinin nasıl çalıştığına bağlı olarak başka komutlara da sahip olabilirsiniz.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.