2009-03-27 38 views
49

thể trùng lặp:
Interface defining a constructor signature?Tại sao chúng ta không được phép chỉ định một hàm tạo trong một giao diện?

Tôi biết rằng bạn không thể chỉ định một constructor trong một giao diện trong Net, nhưng tại sao chúng ta có thể không? Nó sẽ thực sự hữu ích cho dự án hiện tại của tôi để có thể chỉ định rằng một 'động cơ' phải được truyền vào với constructor, nhưng như tôi không thể, tôi phải đáp ứng với một chú thích XML trên lớp đó.

Trả lời

83

Vì giao diện mô tả hành vi. Các nhà xây dựng không phải là hành vi. Làm thế nào một đối tượng được xây dựng là một chi tiết thực hiện.

+21

Tôi nghĩ rằng đó là việc đặt quá nhiều ý nghĩa vào một chi tiết thực hiện: một hàm tạo trong .NET thực sự chỉ là một phương thức được gọi ngay sau khi đối tượng được tạo ra (được cấp phát trong bộ nhớ). Không có lý do gì cũng không thể được định nghĩa là hành vi. Tất nhiên, việc triển khai được tự do khai báo các nhà xây dựng khác, cũng giống như họ có thể quá tải một phương thức thực hiện một giao diện. Các nhà xây dựng trong giao diện sẽ là một tính năng hiếm khi được sử dụng, nhưng không phải là một tính năng vô ích. – EMP

+0

Tôi nghĩ điểm của câu hỏi là: vì nó được xây dựng theo cách này, thực hành tốt nhất là gì? Vì vậy, tôi cho rằng câu trả lời là: bằng cách sử dụng các lớp trừu tượng, vì câu trả lời này nêu rõ: http://stackoverflow.com/a/2804067/1181162 – Vince

0

Vì bạn không thể khởi tạo một giao diện, do đó, một cấu trúc có ý nghĩa.

+5

Các lớp trừu tượng có ý nghĩa như thế nào? – Indrek

28

Bạn sẽ gọi hàm tạo như thế nào? Khi bạn sử dụng các giao diện, bạn thường truyền một thể hiện của giao diện xung quanh (hoặc đúng hơn là một tham chiếu). Cũng nên nhớ rằng nếu một lớp thực hiện một giao diện, một lớp dẫn xuất thừa hưởng giao diện đó, nhưng có thể không có cùng một bộ các hàm tạo.

Bây giờ, tôi có thể thấy việc sử dụng những gì tôi gọi là giao diện tĩnh để chỉ định nhà thầu và các thành viên khác về cơ bản tĩnh để sử dụng trong các phương pháp chung. Xem my blog post on the idea để biết thêm thông tin.

+0

+1 Tôi nghĩ rằng đây sẽ là một bổ sung tuyệt vời cho .NET và tôi đã upvoted mục Connect feedback có liên quan: https://connect.microsoft.com/VisualStudio/feedback/details/412848/allow-structural-type-constraints -cho-generic-type-parameters – EMP

+0

Tôi có thể nghĩ đến ba tính năng đẳng cấp của giao diện: (1) triển khai mặc định cho các phương thức hoặc thuộc tính (lưu ý rằng các giao diện kế thừa sẽ không thể ghi đè lên các cơ sở); (2) cho phép cùng một định danh để có hiệu quả gấp đôi như một giao diện và một lớp tĩnh; (3) xác định một phương pháp tĩnh được sử dụng khi "mới" được gọi trên giao diện. Lưu ý rằng # 2 và # 3 sẽ là cú pháp đường, nhưng tôi nghĩ chúng sẽ làm cho một số thứ sạch hơn. Nếu .net được hỗ trợ # 1, các giao diện có thể có các phương thức hoặc thuộc tính mới được thêm vào mà không phá vỡ các triển khai hiện có. – supercat

+0

@supercat: Vâng, tôi đã suy nghĩ về 1 trong một thời gian quá - và như vậy có MS, tôi tin. Có một cuộc phỏng vấn với Vance Morrison, nơi anh ta nói về điều này. –

9

Không, bạn không thể có nhà thầu trên giao diện vì những lý do đã được đăng. Tuy nhiên bạn có thể vào các lớp trừu tượng. Cho phép nói ví dụ bạn có lớp cơ sở này.

public abstract class ClassOne 
{ 
    protected int _x; 
    protected string _s; 

    public ClassOne(int x, string s) 
    { 
     _x = x; 
     _s = s; 
    }   
} 

Lưu ý rằng không có hàm tạo nào không có đối số (hàm tạo mặc định) phải gọi hàm tạo có 2 đối số.

Vì vậy, điều này không hợp lệ và sẽ không biên dịch.

public class ClassTwo : ClassOne 
{ 
    public ClassTwo() 
    { } 
} 

Tuy nhiên điều này hợp lệ và sẽ biên dịch.

public class ClassTwo : ClassOne 
{ 
    public ClassTwo(int x, string s) : base(x, s) 
    { } 
} 

Tôi muốn chỉ ra ở đây rằng trong C# bạn chỉ có thể kế thừa từ một lớp cơ sở. Có nghĩa rằng đây có thể không phải là giải pháp đúng cho tình huống cụ thể nhưng là điều cần suy nghĩ.

Tony.

+0

Vì các lớp không kế thừa các hàm tạo nên tôi nghĩ đây chỉ là một giải pháp một phần vì nó đòi hỏi lớp con để thực thi lời gọi hàm tạo của nó theo một cách đặc biệt, nhưng không đảm bảo rằng lớp con có một hàm tạo có cùng chữ ký. –

9

Trong số tất cả các lý do khác đã được đăng, hãy nhớ rằng một lớp học có thể dễ dàng triển khai một số giao diện; mà constructor nên được sử dụng sau đó?

+1

Có một cú pháp hoàn toàn tốt để thực hiện các phương thức giao diện có cùng chữ ký có thể được sử dụng cho các nhà xây dựng. – Simon

+0

Tôi không chắc là tôi có quan điểm của bạn (có lẽ tôi đã không): Tôi có nghĩa là lớp A có thể triển khai giao diện IAlpha với một hàm tạo không có đối số, IBeta với một hàm tạo với một đối số và IGamma với một hàm tạo với hai đối số: mà constructor nên lớp A thực hiện? –

+0

Ah, đây là câu trả lời duy nhất thực sự hợp lý với tôi.Tất cả các đối số mà bạn không thể khởi tạo một giao diện để lại cho tôi hỏi "Vì vậy, những gì?" Điểm của một giao diện là khai báo rằng một tập hợp các hàm như vậy phải được thực hiện trong bất kỳ lớp nào mà giả định để thực hiện giao diện. Nghe có vẻ hợp lý khi nói rằng một lớp như vậy cũng cần phải thực hiện một hàm tạo dùng tập hợp các đối số cụ thể này. Nhưng đối số của các nhà xây dựng xung đột, giờ đây là một vấn đề. – Jay

6

Các câu trả lời khác đã chỉ ra tại sao không có ý nghĩa để có khai báo hàm dựng trên giao diện. Nhưng từ câu hỏi của bạn, tôi đoán rằng bạn có thể đang tìm kiếm abstract factory pattern.

Để đưa ra một ví dụ dựa trên câu hỏi của bạn: bạn nói rằng bạn muốn bằng cách nào đó tuyên bố rằng 'động cơ' phải được chuyển cho hàm tạo.Bạn có thể làm điều này bằng cách tuyên bố một giao diện riêng cho một dịch vụ xây dựng như thế này:

public interface IGadgetFactory 
{ 
    IGadget CreateGadget(Engine engine); 
} 

Bất kỳ mã mà phải tạo IGadget trường sau đó có thể sử dụng một ví dụ IGadgetFactory thay vì gọi bất kỳ nhà thầu trực tiếp.

0

Bên cạnh những giải thích khác đưa ra ở đây, bạn phải phát minh ra một cú pháp mới cho gọi họ dù sao, vì nếu bạn có hai hay nhiều triển khai trong phạm vi tại dòng:

Dim x as new IDoStuff() 

Whice thực hiện được gọi ?

+0

Tôi đã thiết kế một ngôn ngữ, tôi sẽ cho phép một giao diện đặt tên cho một phương thức tĩnh được sử dụng, do đó, câu lệnh trên sẽ tương đương với ví dụ: 'Dim X Như IDoStuff = IDoStuff_Creator.CreateNew();' – supercat

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