Tại sao PHP có giao diện?


35

Tôi nhận thấy rằng kể từ PHP5, các giao diện đã được thêm vào ngôn ngữ. Tuy nhiên, do PHP được gõ quá lỏng lẻo, nên dường như hầu hết các lợi ích của việc sử dụng giao diện đều bị mất. Tại sao điều này được bao gồm trong ngôn ngữ?


5
Tôi nghĩ rằng câu hỏi chính xác là, tại sao không?
Alberto Fernández

5
bởi vì họ dường như không cung cấp bất kỳ lợi ích nào, vậy tại sao lại bao gồm chúng?
GSto

4
@HorusKol và trước khi chúng được triển khai, chúng không được sử dụng, vì vậy bạn có thể thấy chúng không được sử dụng và vô dụng chỉ là một phiên bản trước đó. Bạn cũng phải đưa ra và hỗ trợ cho tuyên bố rằng việc sử dụng chúng bằng cách nào đó là một sự cải tiến để nói rằng chúng hữu ích.
Rein Henrichs

6
@HorusKol Không đặc biệt chút nào. Thật dễ dàng để chứng minh đề xuất giá trị của búa. Câu hỏi này đang yêu cầu ai đó thể hiện đề xuất giá trị của các giao diện PHP, không chỉ để tuyên bố rằng chúng có giá trị theo cách tranh luận.
Rein Henrichs

3
Và hãy nhớ rằng các giao diện không chỉ về cách gõ. Một giao diện là một hợp đồng nói rằng một lớp thực hiện phải bao gồm các phương thức mà nó đưa ra. Hữu ích cho những thứ như công cụ plugin.
Michael

Câu trả lời:


30

Ưu điểm chính của giao diện trong PHP là các lớp có thể thực hiện nhiều giao diện. Điều này cho phép bạn nhóm các lớp chia sẻ một số chức năng nhưng không nhất thiết phải chia sẻ một lớp cha. Một số ví dụ có thể bao gồm bộ nhớ đệm, đầu ra hoặc truy cập các thuộc tính của lớp theo một cách nhất định.

Trong mã của bạn, bạn có thể kiểm tra xem một lớp có thực hiện giao diện đã cho hay không thay vì kiểm tra tên lớp. Sau đó, mã của bạn sẽ vẫn hoạt động khi các lớp mới được thêm vào.

PHP cung cấp một số giao diện được xác định trước có thể có ích trong các tình huống khác nhau: http://php.net/manual/en/reserved.interfaces.php .

EDIT - Thêm một ví dụ

Nếu bạn có giao diện có tên MyInterface và bạn đang làm việc với nhiều đối tượng thuộc các lớp khác nhau có thể hoặc không thể chia sẻ một số chức năng, giao diện cho phép bạn làm một cái gì đó như thế này:

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

23
Nói cách khác: "bạn hoàn toàn có thể bỏ qua tất cả các lợi ích của các ngôn ngữ được gõ động"
Kamil Tomšík

11
@Kamil, tôi nghĩ về nó nhiều hơn khi có thể tận dụng lợi ích của việc gõ tĩnh mà không phải chịu những hạn chế khi bạn không muốn chúng.
Karl Bielefeldt

9
bạn nghiêm túc chứ? ví dụ? if-then-if-then-if-then-all-time, nghe có vẻ quen không? ah, vâng, lập trình thủ tục.
Kamil Tomšík

23
@Kamil Tomšík Còn một sự xúc phạm về ngôn ngữ của PHP hơn là những người sử dụng nó một cách bất tài. PHP có tất cả các công cụ để lập trình hướng đối tượng hoàn chỉnh. Cho dù bạn có sử dụng chúng hay không là tùy thuộc vào lập trình viên. Hơn nữa, không có gì sai với lập trình thủ tục trong và của chính nó.
Lotus Notes

18
@Kamil - thật kỳ lạ, bằng cách đọc bình luận của bạn, người ta có thể đưa ra kết luận rằng không có if-s trong OOP và bằng cách nào đó, kỳ diệu - mọi thứ sẽ hoạt động. Ồ
Michael JV

23

PHP được gõ lỏng lẻo, nhưng nó có thể được gõ mạnh về những thứ như tham số phương thức.

Hãy xem xét ví dụ sau:

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

Đoạn mã trên sẽ xuất ra:

Đối số 1 được truyền cho drive () phải triển khai giao diện Xe, ví dụ của Porsche đã cho


1
Chắc chắn, nó quá tệ. Bạn có thể có một nullgiá trị mặc định cho tham số, mặc dù.
Emanuil Rusev

5
nhưng nếu drivecần a Car, thì việc vượt qua nullsẽ không hữu ích lắm đâu ...
HorusKol

7
Không bao giờ vượt qua null. Sử dụng một đối tượng "Trường hợp đặc biệt" (giải thích của Google cho Martin Fowler).
Martin Blore

2
@Renesis Nếu bạn đặt giá trị mặc định thành null, bạn có thể chuyển null thành các phương thức gợi ý. (CAR $ car = null) sẽ cho phép bạn gọi phương thức này với null làm đối số. Đây sẽ là một thực hành khá ngớ ngẩn tuy nhiên. Tại sao bạn muốn làm điều đó?
dqhendricks

2
Ví dụ cụ thể: function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);Bạn có thể có $methodNamenhưng không $securityMode.
Nicole

7

Các giao diện cho phép bạn thực hiện nguyên tắc đóng mở, duy trì cơ sở mã được ghép lỏng lẻo và triển khai nhiều mẫu thiết kế OOP tốt nhất.

Chẳng hạn, nếu một lớp chấp nhận một lớp khác làm đối số:

class A {

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

Lớp A và lớp B của bạn bây giờ có khớp nối chặt chẽ và lớp A không thể sử dụng bất kỳ lớp nào khác ngoại trừ B. Gợi ý loại đảm bảo rằng bạn có loại đối số chính xác, nhưng hiện đã gắn kết mối quan hệ giữa A và B.

Hãy nói rằng bạn muốn lớp A có thể sử dụng tất cả các loại lớp có phương thức run (). Đây về cơ bản (nhưng không hoàn toàn) mẫu thiết kế LỆNH. Để giải quyết, thay vào đó bạn sẽ nhập gợi ý bằng giao diện thay vì lớp cụ thể. B họ sẽ triển khai giao diện đó và sẽ được chấp nhận làm đối số cho lớp A. Bằng cách này, lớp A có thể chấp nhận bất kỳ lớp nào sử dụng giao diện đó làm đối số cho hàm tạo của nó.

Loại mã hóa này được sử dụng trong hầu hết các mẫu thiết kế OOP và cho phép NHIỀU thay đổi mã dễ dàng hơn sau đó. Đây là một phần của các nguyên tắc cơ bản của lập trình AGILE.


1
Hoặc bất kỳ lớp con nào của B
Mez

7

@pjskeptic có một câu trả lời hay và @Kamil Tomšík có một nhận xét tốt về câu trả lời đó.

Điều tuyệt vời về các ngôn ngữ được gõ động như PHP là bạn có thể thử sử dụng các phương thức trên các đối tượng và nó sẽ không hét vào bạn trừ khi phương thức không có ở đó.

Vấn đề với các ngôn ngữ được gõ động như PHP là bạn có thể thử sử dụng các phương thức trên các đối tượng và nó sẽ hét vào bạn khi phương thức không có ở đó.

Các giao diện thêm một cách thuận tiện để gọi các phương thức trên một đối tượng không xác định và chắc chắn rằng các phương thức đó ở đó (không nhất thiết là chúng phải chính xác hoặc sẽ hoạt động). Nó không phải là một phần cần thiết của ngôn ngữ, nhưng nó giúp mã hóa thuận tiện hơn. Nó cho phép các nhà phát triển OOP gõ mạnh để viết mã PHP được gõ mạnh, sau đó có thể hoạt động cùng với mã PHP được gõ lỏng lẻo được viết bởi một nhà phát triển PHP khác.

một chức năng như:

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

thuận tiện hơn:

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

và IMHO đơn giản, mã dễ đọc là mã tốt hơn.


1
những gì bạn làm thay vào đó chỉ là không kiểm tra phương thức và gặp sự cố và ghi khi ai đó gọi hàm của bạn với dữ liệu sai. Đó không phải là vấn đề của bạn nếu ai đó sử dụng sai chức năng của bạn.
Raynos

không chính xác - ví dụ của bạn là cơn ác mộng đối với bất kỳ ai muốn vượt qua bất kỳ "con vịt" năng động nào, như proxy, bộ chuyển đổi, trang trí, v.v.
Kamil Tomšík

1
@Kamil? Làm sao vậy Một proxy sẽ là một lớp bao bọc cho một cái gì đó không thực hiện giao diện để cho phép nó được sử dụng với chức năng này.
tylermac

@tylermac proxy động sử dụng __call () - và nếu __call là phương thức duy nhất ở đó, đơn giản là nó không thể triển khai IBar, có nghĩa là bạn không thể chuyển nó tới foo (thanh IBar $)
Kamil Tomšík

5

Chúng hoàn toàn vô dụng nếu bạn là người đánh vịt, thực ra khi bạn gõ vịt, thật khó chịu khi làm việc với các thư viện / khung sử dụng bất kỳ gợi ý kiểu nào.

Điều này cũng áp dụng cho tất cả các loại lập trình meta động (phương pháp ma thuật).


3

PHP không phải là lỏng lẻo hoặc mạnh mẽ, nhưng được gõ động .

Về giao diện, điều đầu tiên bạn nên tự hỏi mình là: hầu hết những lợi ích của giao diện là gì?

Trong OOP, giao diện không chỉ là về các loại, mà còn về hành vi.

Vì PHP cũng có một tính năng gợi ý kiểu , bạn có thể sử dụng các giao diện giống như trong ngôn ngữ oo thuần túy, chẳng hạn như 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
        }
    }
}

Với việc triển khai giao diện PHP, bạn cũng tạo các mô phỏng cho các lớp trừu tượng bằng PHPUnit - và đây là một tính năng tuyệt vời:

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

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

    // do your assertions
}

Vì vậy, về cơ bản, bạn có thể có một ứng dụng tương thích RẮN trong PHP bằng cách sử dụng các tính năng ngôn ngữ, một trong số đó là các giao diện.


0

Các giao diện là hữu ích cho tiêm phụ thuộc nhiều hơn so với bê tông. Như một ví dụ về 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);

Bây giờ nói nếu nhu cầu của bạn thay đổi và bạn muốn lưu vào pdf. Bạn có thể tạo một lớp mới cho mục đích đó thay vì làm ô nhiễm lớp Bài viết.

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);

Lớp Article hiện có một hợp đồng mà các lớp nó sử dụng để lưu phải thực hiện giao diện Istore. Nó không quan tâm nơi nó tiết kiệm hoặc làm thế nào nó tiết kiệm.


-1

Bạn có thể cung cấp các đối tượng thực "Giả" thực hiện giao diện. Sau đó, bạn có thể kiểm tra một phần mã của mình mà không yêu cầu máy chủ thực, hệ thống tệp, ổ cắm, cơ sở dữ liệu, v.v.


-3

Rất nhiều người có thể sẽ ghét tôi vì đã trả lời theo cách này nhưng giải pháp cho các vấn đề đánh máy của bạn có thể dễ dàng khắc phục bằng PHP. PHP được gõ lỏng lẻo nên các loại được mặc định giả định, điều này có thể gây ra một số vấn đề, đặc biệt là trong các hoạt động so sánh mà hầu hết mọi người đều gặp vấn đề với nó. Điều đó đang được nói, PHP có thể nghiêm ngặt như bất kỳ ngôn ngữ được gõ mạnh nào nếu bạn sử dụng những gì bạn đang sử dụng vào loại bạn cần, và sau đó sử dụng các toán tử so sánh bit. Đây là ví dụ dễ nhất tôi có thể nghĩ về những gì tôi đang nói:

$ myVar = (int) 0; $ myOtherVar = '0';

so sánh ($ myVar == $ myVar) sẽ bằng (bool) đúng

nhưng so sánh ($ myVar === $ myVar) sẽ bằng (bool) sai giống như bất kỳ so sánh "gõ" nào

Tôi thực sự chỉ mong các nhà phát triển sẽ ngừng tranh luận về những điều này, nếu bạn gặp vấn đề với cách PHP hoạt động hoặc lập trình trong java và sống và để sống, hoặc sử dụng nó theo cách nó sẽ làm những gì bạn muốn. Bitching về nó làm gì tốt cho bạn anyway? Cung cấp cho bạn một cái cớ để vít xung quanh cả ngày? Làm cho bạn trông tốt hơn so với người khác? Thật tuyệt khi bạn cảm thấy rất cao về bản thân mình rằng bạn sẵn sàng làm cho người khác xấu đi nhưng thực tế đó là sở thích của bạn và buộc niềm tin của bạn vào bất cứ ai thực sự chỉ khiến họ viết mã theo cách họ không thoải mái khi gây ra ba điều:

1) Họ sẽ mã hóa theo cách của bạn nhưng "lộn xộn" theo tiêu chuẩn của bạn (nghĩ rằng, bạn đã bao giờ thấy một lập trình viên java tạo chương trình PHP đầu tiên của họ hay ngược lại chưa? Nó sẽ giống như cách thay đổi phương pháp của họ hoặc thậm chí tệ hơn.)

2) Bạn sẽ tìm thấy một cái gì đó khác để than vãn về

3) Có thể sẽ mất nhiều thời gian hơn để họ sản xuất. Và có thể nó sẽ khiến bạn trông tốt hơn trong thời gian ngắn, nhưng toàn bộ nhóm sẽ trông tệ hơn vì điều đó (hãy nhớ rằng bạn có thể viết mã chậm hơn người khác và điều đó không hẳn là xấu miễn là nhóm đáp ứng các sản phẩm giao trong một khung thời gian hợp lý, nhưng việc ép buộc thói quen của bạn lên một người thường thực hiện nhanh hơn một chút có thể sẽ khiến cả nhóm của bạn chậm lại, do đó, trông tệ hơn trong một quy trình làm việc rất đòi hỏi)

Cá nhân tôi thích viết mã PHP theo thủ tục mặc dù tôi có thể và đã viết các chương trình đầy đủ bằng OOP bằng một vài ngôn ngữ khác nhau. Điều đó đang được nói, tôi đã thấy mã OOP tốt và mã OOP xấu, mã thủ tục tốt và mã thủ tục xấu cho vấn đề đó ... Nó thực sự không liên quan gì đến thực tiễn, nhưng với thói quen mà bạn sử dụng và thậm chí sau đó, Rất nhiều điều là cảm xúc được giải thích của tôi ... điều đó không có nghĩa là tôi sẽ nói xấu về những nhà phát triển đó hoặc nói khoe khoang với "cách của tôi là tốt nhất" BS, nó phù hợp với tôi, và công ty tôi làm việc rất tốt hạnh phúc với công việc của tôi và tôi tự hào về điều đó. Có nhiều lý do nên thiết lập một tiêu chuẩn nhưng những gì bạn đưa vào tiêu chuẩn bạn chọn là RẤT quan trọng ... Cảm ơn vì đã để tôi đưa nó ra khỏi ngực. Có một ngày tuyệt vời.


-4
  1. Giao diện là một phần của mô hình OOP. Vì vậy, nó rất hữu ích trong nhiều trường hợp khi bạn cố gắng tạo các bộ phận hướng đối tượng hoặc hệ thống của bạn.
  2. Vì thế. Tại sao không? ;-)

Ví dụ: Bạn cần lưu trữ dữ liệu của bạn. Làm sao? Có rất nhiều công cụ khác nhau để lưu vào bộ đệm, cái nào là tốt nhất? Ai quan tâm nếu bạn có lớp trừu tượng có giao diện ICacheDriver với một tập hợp các phương thức như key, get, put, Clear, v.v. Chỉ cần thực hiện cho nó những gì bạn cần trong dự án hiện tại và thay đổi nó khi bạn cần một phương thức khác. Hoặc sử dụng đơn giản của toString. Bạn có một bộ các đối tượng hiển thị khác nhau. Bạn chỉ cần thực hiện giao diện Stringable (mô tả phương thức toString [không có giao diện thực sự như trong PHP, nhưng chẳng hạn]) và chỉ giao thoa trên tất cả các đối tượng của bạn với (chuỗi) $ obj. Có tất cả những gì bạn cần làm thay vì chuyển đổi (true) {case $ obj isntanceof A1: "do 1"; phá vỡ; ...}

Đơn giản. Vì vậy, không có câu hỏi "Tại sao?". Có "làm thế nào để sử dụng tốt hơn?". ;-) Chúc may mắn.


-5

Tôi đoán.

PHP được sử dụng bởi nhiều lập trình viên cấp đầu vào, lập trình viên cấp nhập cảnh được dạy java ở trường đại học.

Sau khóa học Lập trình 101, họ bắt đầu cằn nhằn Zend, họ muốn có các tính năng java bởi vì đó là cách họ được dạy để suy nghĩ, suy nghĩ theo cách riêng của bạn (hoặc hiểu cách gõ vịt) thật khó, khi bạn chỉ mới 20 tuổi.

Zend rất thực dụng, việc thêm tính năng này sẽ dễ dàng hơn là giả vờ chúng ở đâu cũng đúng.
Điều này cũng mua ở nhiều người dùng hơn thay vì khiến họ rời đi, vì vậy nó phải tốt.

Một ví dụ khác của quá trình này? Mọi người mới ra khỏi các khóa học .NET và Java cũng muốn các Khung công tác lớp , họ cằn nhằn về điều đó cho đến khi Zend nảy ra Khung công tác Zend . Điều này mua ở nhiều người dùng hơn. Và trên và trên ...

(tính năng ngôn ngữ duy nhất mà nhóm PHP được biết là đã đấu tranh chống lại , trong nhiều năm qua, là goto)


Trong tầm nhìn của tôi, PHP12có lẽ sẽ có tất cả các tính năng cú pháp của thế giới (tôi hy vọng nó không có thời gian chạy lớp trừu tượng, khó khăn, vì đó là thứ đã giết chết perl) với một cái nháy mắt cho các mô hình chức năng và kiểu dữ liệu, nhưng vẫn không có goto.
ZJR

"Thật khó, khi bạn chỉ mới 20" Làm thế nào tuổi tác có thể có bất cứ điều gì để hiểu bất kỳ khái niệm nào trong số đó?
Evicatos

@Evicatos học sinh trung học sắp xếp chương trình, nhưng họ thường có những giáo viên tồi, quy ước đặt tên kém và tạo ra những đốm sáng không thể nhầm lẫn. Họ học lập trình ngay khi bắt đầu học đại học, phải mất một vài năm để có được nó. Sau đó, họ bắt đầu chuyển hướng từ những ngôn ngữ khó đánh máy, công nghiệp, được hoan nghênh, những ngôn ngữ mà họ đã được dạy trong những năm đầu tiên, và chuyển sang những ngôn ngữ thực dụng hơn, gõ vịt. Tôi tin rằng đây là một bushido nhiều lập trình viên chia sẻ. Sau đó, một lần nữa, điều này có thể không phản ánh kinh nghiệm của bạn, bạn có thể là một người hiểu biết tự học. Nếu vậy, chỉ cho chúng tôi cách.
ZJR
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.