2010-08-01 23 views
7

Một trong những nguyên tắc thiết kế chính là chương trình cho một giao diện không phải là triển khai thực hiện. Điều này thậm chí có thể trong php hoặc bất kỳ ngôn ngữ khác gõ nhẹ.Chương trình cho một giao diện không thực hiện trong php

EDIT:

Tôi có thể đã không viết câu hỏi rõ ràng như tôi nên có. Tôi không có nghĩa là php không thể sử dụng giao diện - nó obvisouly có thể. Tôi có nghĩa là nguyên tắc thiết kế "chương trình cho một giao diện và không phải là một thực hiện" trở nên thừa trong các ngôn ngữ đánh máy yếu.

+0

Xem bài đăng đã chỉnh sửa của tôi. Tôi không thể thấy tại sao nó sẽ là "dư thừa" – NullUserException

Trả lời

4

Có. Xác định giao diện:

interface iTemplate 
{ 
    public function setVariable($name, $var); 
    public function getHtml($template); 
} 

Và thực hiện nó:

PHP thủ
// Implement the interface 
class Template implements iTemplate 
{ 
    private $vars = array(); 

    public function setVariable($name, $var) 
    { 
     $this->vars[$name] = $var; 
    } 

    public function getHtml($template) 
    { 
     foreach($this->vars as $name => $value) { 
      $template = str_replace('{' . $name . '}', $value, $template); 
     } 

     return $template; 
    } 
} 

trên giao diện: http://php.net/manual/en/language.oop5.interfaces.php

Tôi không biết tại sao nó sẽ không thể có giao diện chỉ vì ngôn ngữ bị nhập sai.


EDIT: Điểm (nhiều hơn hoặc ít hơn) của việc có một giao diện là để bạn có thể tái sử dụng mã của bạn không phụ thuộc vào lớp mà thực sự thực hiện cho biết giao diện.

Giả sử chương trình của bạn sử dụng giao diện Set, có phương thức addItem(), removeItem() và . Với các giao diện, bạn biết bạn sẽ có thể gọi bất kỳ phương thức nào trong số 3 phương thức này bất kể triển khai thực hiện Set bên dưới, có thể là HashSet, TreeSet hay bất kỳ thứ gì.

Điều này không thay đổi nếu bạn đang sử dụng ngôn ngữ được nhập yếu; bạn vẫn có thể viết mã như thể bạn đang sử dụng một ngôn ngữ được đánh máy mạnh. Tôi biết tôi đã không từ giải thích này thực sự tốt, nhưng tôi hy vọng bạn sẽ có được ý tưởng.

0

php có interfaces và bạn có thể lập trình cho họ. Tại sao bạn không thể làm điều đó?

Lập trình cho giao diện nghĩa là bạn chỉ cần sử dụng chức năng được cung cấp bởi giao diện và không dựa vào chi tiết triển khai cũng như không sử dụng chức năng khác do triển khai cung cấp và bạn chỉ biết điều đó, thay đổi (giao diện không nên).

+0

Vâng, toàn bộ quan điểm của nguyên tắc dường như trở thành vô nghĩa khi bạn không sử dụng các loại. Chắc chắn bạn có thể sử dụng giao diện trong php, im rõ ràng là không tranh chấp đó, tôi nói nhiều hơn rằng nguyên tắc không hiệu quả khi bạn không thể sử dụng kiểu đối tượng. Ví dụ trong một ngôn ngữ kiểu mạnh bạn sẽ sử dụng: Loại t = new ConcreteType - trong php bạn chỉ cần nói $ t = new ConcreteType. Chắc chắn ConcreteType sẽ thực hiện giao diện nhưng mã instanciating không biết gì về điều này. Có lẽ im hiểu lầm nguyên tắc. – David

+0

@David Họ chắc chắn mất một số lợi thế của họ trong một ngôn ngữ đánh máy yếu, nhưng chúng vẫn hữu ích nếu được sử dụng đúng cách. – NullUserException

+0

Nhưng nguyên tắc được dự định để "Khi bạn chỉ phụ thuộc vào giao diện, bạn đã tách khỏi việc thực hiện" E Gama, nhưng bằng ngôn ngữ gõ nhẹ, bạn chỉ đơn giản sử dụng lớp bê tông khi khởi tạo. Tôi không thể thấy nguyên tắc áp dụng ở đây như thế nào. Tôi có lẽ chỉ là ngu ngốc nhưng nó chen chúc tôi vì một lý do nào đó. – David

0

Phụ thuộc vào ý bạn là "giao diện" và "triển khai". Đây là những thuật ngữ lỏng lẻo có ý nghĩa có thể thay đổi tùy thuộc vào ngữ cảnh.

PHP5 chứa cấu trúc OOP tương tự như Java và C#, chẳng hạn như Đối tượng dưới dạng tham chiếu, Lớp học, Lớp trừu tượng và Giao diện. Nó cũng chứa gợi ý kiểu cho paramaters phương thức. Những công cụ này có thể được sử dụng để xây dựng "một giao diện" cho một cái gì đó.

0

Mục tiêu cuối cùng là có giao diện mà mỗi thành phần đồng ý. Vì vậy, nếu, ví dụ, tôi đã xây dựng một trang web JavaScript đã được thực hiện -entirely- trong một MVC cũ (non-Rails/PHP) thực hiện, và hoàn toàn trong AJAX, tôi sẽ đảm bảo rằng mỗi các thành phần thực hiện cùng một giao diện để quan sát.

Trong mỗi mô hình/chế độ xem/bộ điều khiển, tôi có thể đặt tên cho phương thức "đăng ký" của mình hoàn toàn khác. Hoặc, tôi có thể triển khai giao diện chuẩn cho từng giao diện.

Vì vậy, tôi có thể có phương thức ".Register (event_type, subscriptioning_class)" công khai được triển khai trong MỌI thành phần đơn lẻ có thể được mong đợi sẽ được gọi.

Tương tự như vậy, tôi có thể có phương thức công khai ". Cập nhật (event_type, dữ liệu)" được thực hiện trong MỌI thành phần đơn lẻ có thể được mong đợi sẽ được gọi.

.Register và .Update là giao diện cho giao tiếp Observer của tôi. Bên trong các lớp học của tôi, mỗi lớp có thể có phương thức ".Subscribe (publisher, event_type, self_reference)". Đó là phương pháp chỉ có thể là:

Class.Subscribe = function (publisher, event_type) { 
    var self_reference = this; 
    publisher.Register(event_type, self_reference); 
}; 

Mỗi có thể có một phương pháp .Notify nội bộ:

Class.Notify = function (type, data) { 
    var subscribers = this.subscribers[type], 
     i = 0, l = subscribers.length; 

    for (; i < l; i++) { subscribers[i].Update(type, data); } 
}; 

tôi đã đồng ý rằng tất cả các giao diện truyền thông của tôi sẽ cư xử theo cách này, nó không quan trọng những gì tôi trông như thế nào.

Mô hình của tôi có thể tiếp tục bị lãng quên với Chế độ xem của tôi và Chế độ xem của tôi có thể tiếp tục bị lãng quên với Bộ điều khiển của tôi.

Thông báo .Notify và .Subscribe không cần phải được triển khai theo cách đó - chúng không phải là một phần của giao diện có thể truy cập công khai. Họ có thể là bất cứ điều gì tôi muốn.

. Đăng ký có thể mất một ARRAY nhà xuất bản và đẩy nó qua vòng lặp for, để đăng ký nhiều điểm dữ liệu. Hoặc lấy một mảng {"pub": x, "type": y} đối tượng literals, và gọi phương thức .Register của mỗi một, để bạn có thể nhận được TẤT CẢ bootstrapping của lớp đó ra khỏi con đường với một cuộc gọi chức năng.

Điều tương tự cũng xảy ra khi tạo ứng dụng trình phát âm thanh. Tôi không quan tâm đến những tài sản công khai mà MusicPlayer chia sẻ. Tôi biết rằng nó sử dụng .Play(), .Pause(), .Stop(), .Load (track).

Nếu tôi đảm bảo rằng tôi CHỈ sử dụng các phương thức giao diện công cộng đã thỏa thuận, chương trình sẽ hoạt động. Tại sao?

Vì người làm việc trên MusicPlayer có thể thay đổi nội bộ của MusicPlayer. Anh ấy có thể viết lại chúng hoàn toàn. Có thể có phương thức ._ precacheSong (theo dõi). Nhưng nếu nó được thay thế bằng. _cueTrack (theo dõi) xuống đường?

Bạn chỉ sử dụng một số tiện ích con và một ngày tiện ích của bạn gặp sự cố, vì bạn đã mở rộng hoặc triển khai tiện ích dựa trên phương pháp không giao diện hoặc dữ liệu không giao diện, đã xảy ra thay đổi như v1.2.1

Vì vậy, ngay cả trong Ngôn ngữ Loose, Giao diện cũng quan trọng. Chúng cung cấp cho bạn một bản đồ về cách bạn có thể mong đợi để gọi bất kỳ thành phần nào được mong đợi có chức năng đó - và bất kể các thành phần của thành phần đó hoạt động như thế nào, các đầu vào và đầu ra sẽ giống nhau (mặc dù có nhiều kiểu/lỗi hơn) kiểm tra là cần thiết trên đầu vào).

Chúng cho phép bạn "Duck-Type" thực sự dễ dàng (lấy danh sách các phiên bản Class khác nhau - kích hoạt cùng một cuộc gọi hàm trên mỗi trường hợp, mong đợi từng có cùng một phương thức và có cùng định dạng dữ liệu).

Thậm chí tốt hơn với JavaScript:

tôi đang .Subscribe thậm chí có thể được viết chỉ một lần, và sau đó bị ràng buộc vào bất cứ điều gì mà tôi muốn "thừa hưởng" nó.

Interface.Subscribe = function (publisher, evt_type) { 
    var self_ref = this; 
    publisher.Register(evt_type, self_ref); 
}; 

Class_1.Subscribe = Interface.Subscribe.bind(Class_1); 
Class_2.Subscribe = Interface.Subscribe.bind(Class_2); 
Class_3.Subscribe = Some_Other_Interface.Subscribe.bind(Class_3); 

Và tôi có thể làm điều đó một cách tự do, bởi vì tôi biết rằng mọi thứ tôi muốn đăng ký sẽ có cùng giao diện công khai.

Các vấn đề liên quan