it-swarm-eu.dev

Proč PHP má rozhraní?

Všiml jsem si, že od PHP5 byla do jazyka přidána rozhraní. Nicméně, protože PHP je tak volně napsáno), zdá se, že většina výhod používání rozhraní je ztracena. Proč je to součástí jazyka?

34
GSto

Hlavní výhodou rozhraní v PHP je, že třídy mohou implementovat více rozhraní. To vám umožňuje seskupovat třídy, které sdílejí některé funkce, ale nemusí nutně sdílet rodičovskou třídu. Některé příklady mohou zahrnovat ukládání do mezipaměti, výstup nebo určitým způsobem přistupovat k vlastnostem třídy.

V kódu můžete místo kontroly názvu třídy zkontrolovat, zda třída implementuje dané rozhraní. Poté bude váš kód fungovat i po přidání nových tříd.

PHP poskytuje některá předdefinovaná rozhraní, která se mohou hodit v různých situacích: http://php.net/manual/en/reserved.interfaces.php .

ÚPRAVA - Přidání příkladu

Pokud máte rozhraní s názvem MyInterface a pracujete s více objekty různých tříd, které mohou nebo nemusí sdílet některé funkce, rozhraní vám umožní něco podobného:

// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
 if($obj instanceof MyInterface) {
     $obj->a();
     $obj->b();
     $obj->c();
   }
}
31
pjskeptic

PHP je volně psáno, ale může být silně psáno o věcech, jako jsou parametry metody.

Zvažte následující příklad:

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

Výše uvedený kód by výstup:

Argument 1 předaný do drive () musí implementovat rozhraní Car, což je instance Porsche

23
Emanuil Rusev

Rozhraní vám umožňují implementovat princip otevřeného uzavření, udržovat volně propojenou kódovou základnu a implementovat mnoho nejlepších návrhových vzorů OOP).

Pokud například jedna třída přijme jinou argument jako argument:

class A {

    public function __construct(B $class_b) {
        // use class b
        $class_b->run();
    }
}

Vaše třída A a třída B mají nyní těsné spojení a třída A nemůže používat žádnou jinou třídu kromě B a jejích podtříd. Typový tip zajišťuje, že máte správný typ argumentu, ale nyní utvrdil vztah mezi A a B.

Řekněme, že chcete, aby třída A mohla používat všechny typy tříd, které mají metodu run (). Toto je v zásadě (ale ne zcela) vzorový vzor COMMAND. Chcete-li to vyřešit, namísto konkrétní třídy byste místo toho napsali tip pomocí rozhraní. B by pak implementovalo toto rozhraní a bude přijato jako argument pro třídu A. Tímto způsobem třída A může akceptovat jakoukoli třídu, která používá toto rozhraní jako argument pro svého konstruktora.

Tento typ kódování se používá ve většině návrhů OOP návrhové vzory) a umožňuje MUCH snadnější změny kódu v pozdějším čase, které jsou součástí základů programování AGILE.

class A {

    public function __construct(C $interface_c) {
        // use any class that implements interface C
        $interface_c->run();
    }
}

interface C {

    public function run();
}

class B implements C {

    public function run() {
        // do something
    }
}
8
dqhendricks

@pjskeptic má dobrá odpověď a @ Kamil Tomšík má k této odpovědi dobrý komentář.

Skvělá věc, o dynamicky zadávaných jazycích, jako PHP, je, že můžete zkusit použít metody na objekty a nebude na vás křičet, pokud tam metoda neexistuje).

Problém s dynamicky zadanými jazyky, jako je PHP, je, že můžete zkusit použít metody na objekty a bude křičet na vás, když tam metoda neexistuje).

Rozhraní přidávají pohodlný způsob volání metod na neznámý objekt a jsou si jisti, že tyto metody existují (ne že jsou nutně správné nebo že budou fungovat). Není to nezbytná součást jazyka, ale usnadňuje kódování. Umožňuje silně zadaný OOP psát silně zadaný PHP kód, který pak může pracovat vedle volně zadaného PHP kód) jiným vývojářem PHP).

funkce jako:

foo( IBar $bar )
{
  $baz = $bar->baz();
  ...
}

je výhodnější než:

foo( $bar )
{
  if ( method_exists( $bar, 'baz' ) )
  {
    $baz = $bar->baz();
  }
  else
  {
    throw new Exception('OMGWTF NO BAZ IN BAR!');
  }
  ...
}

a jednoduchý, čitelný kód IMHO je lepší kód.

7
zzzzBov

Jsou naprosto zbytečné, pokud jste psací stroj, vlastně když děláte psací stroj, je docela nepříjemné pracovat s knihovnami/framework, které používají jakýkoli typový tip.

To platí také pro všechny druhy dynamického meta-programování (magické metody).

5
Kamil Tomšík

PHP není není volně ani silně, ale dynamicky zadávané .

Pokud jde o rozhraní, první věc, kterou byste si měli položit, je: jaké jsou výhody rozhraní?

V OOP nejsou rozhraní jen o typech, ale také o chování.

Protože PHP má také funkce typu nápověda ), můžete rozhraní používat stejně jako v čistém jazyce oo, jako je Java.

interface File
{
    public function getLines();
}

CSVFile implements File
{
    public function getLines()
    {}
}

XMLFile implements File 
{
    public function getLines()
    {}
}

JSONFile implements File 
{
    public function getLines()
    {}
}

class FileReader
{
    public function read(File $file)
    {
        foreach($file->getLines() as $line)
        {
            // do something
        }
    }
}

S implementací rozhraní PHP) můžete také vytvářet simulátory pro abstraktní třídy pomocí PHPUnit - a to je sakra funkce:

public function testSomething()
{
    $mock = $this->getMockForAbstractClass('File');

    $mock->expects($this->once())
         ->method('getLines')
         ->will($this->returnValue(array()));

    // do your assertions
}

Takže v podstatě můžete mít SOLIDNÍ kompatibilní aplikaci v PHP pomocí jazykových funkcí, z nichž jednou jsou rozhraní) .

3
Daniel Ribeiro

Rozhraní jsou užitečná pro vstřikování závislosti mnohem více než beton. Jako příklad barebones:

interface Istore { 
  public function save(); 
}

class Article_DB implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}

class Article
{
   private $content;

   public function content($content)
   {
     $this->content = $content;
   }

   public function save(Istore $store)
   {
     $store->save($this->content);
   }
}

$article = new Article();
$article->content('Some content');

$store = new Article_DB();
$article->save($store);

Nyní řekněte, zda se vaše potřeby změní a chcete uložit do formátu PDF. Za tímto účelem byste mohli vytvořit novou třídu namísto znečišťování třídy článku.

class Article_PDF implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}


$article = new Article();
$article->content('Some content');

$store = new Article_PDF();
$article->save($store);

Třída Article má nyní smlouvu, že třídy, které používá k uložení, musí implementovat rozhraní Istore. Nezáleží na tom, kde šetří nebo jak šetří.

0
Pete