2011-07-12 38 views
17

Trong nhiều trường hợp, câu hỏi thậm chí không tự hỏi, vì đôi khi thừa kế cung cấp các tính năng cần thiết mà các mẫu không thể cung cấp. Ví dụ, khi tôi cần phải giải quyết các loại khác nhau thông qua một loại cơ sở (đa hình), tôi cần phải sử dụng thừa kế.Khi nào tôi nên sử dụng các mẫu thay vì thừa kế và ngược lại?

Tuy nhiên, có một số trường hợp mà vấn đề có thể được giải quyết cả với thừa kế, cũng như mẫu.

Hãy cho chiến lược ví dụ mô hình giống như parametrization của một số phần của mã:

Một giải pháp của một tập tin-phân tích cú pháp có thể trông như thế này:

class FileParser 
{ 
    //... 
    public: 
     void Parse(ParsingAlgorithm* p); 
    //... 
} 

void FileParser::Parse(ParsingAlgorithm* p) 
{ 
    m_whatevertypeofvaluesineed = p->Parse(whateverparametersyouneed); 
} 

nơi ParsingAlgorithm là một lớp cơ sở trừu tượng, cung cấp một số phương thức cơ bản và cần được kế thừa bởi bất kỳ ai thích thực hiện một trình phân tích cụ thể cho lớp FileParser.

Tuy nhiên, tương tự một cách dễ dàng có thể đạt được bằng mẫu:

template <class Parser> 
class FileParser 
{ 
    //... 
    public: 
     void Parse() 
     { 
      m_whatevertypeofvaluesineed = m_parser.Parse(whateverparametersyouneed); 
     } 

    private: 
     Parser m_parser; 
    //... 
} 

Có một số quy tắc chung mà tôi có thể sử dụng để quyết định có nên sử dụng các mẫu hoặc thừa kế? Hoặc tôi chỉ nên sử dụng mẫu ở bất kỳ nơi nào có thể, để tránh chi phí thời gian chạy của những thứ như chức năng ảo?

+0

hơi trùng lặp của [Có thể CRTP thay thế hoàn toàn chức năng ảo cho thiết kế nhỏ hơn không?] (Http://stackoverflow.com/questions/6613779/can-crtp-completely-replace-virtual-functionality-for-smaller-designs) – iammilind

Trả lời

17

Nếu bạn biết trong thời gian biên dịch những đối tượng bạn sẽ thao tác, thì đa hình tĩnh với mẫu thường là cách nhanh nhất, và nó tạo mã ngắn gọn hơn một chút (không cần thừa kế rõ ràng) . Nó cũng có thể chung chung hơn khi bạn không bị giới hạn trong một hệ thống phân cấp lớp mạnh.

Nếu bạn muốn đa hình thời gian chạy, thì bạn không có lựa chọn nào ngoài việc sử dụng con trỏ, thừa kế và chi phí nhỏ của các chức năng ảo.

ý kiến ​​riêng của tôi:

  • Sử dụng các mẫu khi có thể, nó cảm thấy thoải mái
  • Sử dụng thừa kế để factorise mã (nhưng không có bộ sưu tập heterogenous), nhưng hãy cẩn thận với cắt.
  • Đừng lo lắng về các vấn đề hiệu suất của các cuộc gọi ảo
  • Đôi khi bạn không có sự lựa chọn và bạn muốn bộ sưu tập hetergenous kéo xung quanh nỗi đau của việc sử dụng con trỏ
4

Mẫu cung cấp Đa hình thời gian biên dịch thay vì đa hình thời gian chạy do thừa kế cung cấp. Tôi thích sử dụng các mẫu khi có thể.

Bài viết này trên Templates and Inheritance giải thích chi tiết.

-1

Đề xuất của tôi là không sử dụng trong trường hợp này và sử dụng các chức năng riêng biệt cho từng loại tệp;

Stream stream = open(filepath); 

    Image image = ParseBMP(stream); 
    // ...or 
    Image image = ParseJPG(stream); 

Không cần phải làm mọi thứ phức tạp hơn chúng.

+0

Bạn nói đúng, nhưng ví dụ của tôi được cho là một ví dụ nhanh về loại tình huống trong đó câu hỏi "kế thừa so với mẫu" có thể xuất hiện. – TravisG

+0

Tôi không đồng ý. Sử dụng các chức năng khác nhau là chống lại các hiệu trưởng mở http://en.wikipedia.org/wiki/Open/closed_principle –

+0

Không bao giờ nghe về hiệu trưởng đó trước đây, nhưng nó có vẻ như là điều ác đối với tôi. –

3

Templates thường performant hơn khi chạy, vì hơn công việc được thực hiện tại thời gian biên dịch.Mặt khác, chúng có thể phức tạp hơn, do đó khó viết và hiểu được. Vì vậy, tốt nhất là nên sử dụng chúng bất cứ khi nào bạn có thể khi không vượt quá toàn bộ giải pháp. Ví dụ của bạn, chúng không chính xác về mặt chức năng: biến thể đầu tiên cho phép yêu cầu bạn tạo cá thể của trình phân tích cú pháp khi chạy, trong khi biến thể thứ hai yêu cầu trình phân tích cú pháp phải chọn.

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