Làm thế nào có thể thiết kế cho thừa kế gây ra chi phí thêm? [đóng cửa]


12

Vì vậy, tôi muốn kế thừa từ một sealed classtrong CSharp và bị đốt cháy. Không có cách nào để mở khóa nó trừ khi bạn có quyền truy cập vào nguồn.

Sau đó, nó khiến tôi suy nghĩ "tại sao sealedthậm chí tồn tại?". 4 tháng trước. Tôi không thể tìm ra nó, mặc dù đọc nhiều điều về nó, chẳng hạn như:

Tôi đã cố gắng tiêu hóa tất cả những thứ đó kể từ đó, nhưng nó chỉ là quá nhiều đối với tôi. Cuối cùng, ngày hôm qua tôi đã thử lại. Tôi đã quét qua tất cả chúng một lần nữa, cộng thêm vài lần nữa:

Cuối cùng, sau nhiều suy ngẫm, tôi quyết định chỉnh sửa mạnh câu hỏi ban đầu dựa trên tiêu đề mới.

Câu hỏi cũ quá rộng và chủ quan. Về cơ bản nó đã hỏi:

  1. Trong tiêu đề cũ: Một lý do chính đáng để sử dụng niêm phong
  2. Trong cơ thể: Làm thế nào để sửa đổi một lớp kín? Quên về thừa kế? Sử dụng thành phần?

Nhưng bây giờ, sự hiểu biết (mà tôi đã không làm ngày hôm qua) rằng tất cả đều sealedngăn cản sự kế thừa , và chúng ta thực sự có thể và nên sử dụng thành phần trên sự kế thừa , tôi nhận ra những gì tôi cần là những ví dụ thực tế .

Tôi đoán câu hỏi của tôi ở đây là (và trên thực tế luôn luôn như vậy) chính xác những gì Mr.Mindor gợi ý cho tôi trong một cuộc trò chuyện : Làm thế nào để thiết kế cho thừa kế có thể gây thêm chi phí?


5
Câu hỏi được diễn đạt khá tích cực và nghe có vẻ như một câu nói. Bạn nên điều chỉnh lại nếu bạn muốn câu trả lời phù hợp và khách quan.
Euphoric

11
Xem tại sao rất nhiều lớp khung được niêm phong? bởi Eric Lippert. Ông cung cấp một số lý do tốt để đóng dấu các lớp học.
Robert Harvey

9
Sau đó, bạn đã không đọc bài viết. Quay lại và đọc nó một lần nữa. Nó hiểu rõ điều này: bạn không thể dự đoán được vô số cách mà khách hàng có thể phá vỡ lớp của bạn bằng cách mở rộng nó. Bạn có thể đổ lỗi cho khách hàng của mình vì điều đó, nhưng bạn là người sẽ phải hỗ trợ họ.
Robert Harvey

4
@Cawas Anh ấy có thể, hoặc bạn có thể đọc bài viết mà anh ấy liên kết giải thích chi tiết. Ông chỉ tóm tắt bài báo đó với bình luận của mình.
Phục vụ

7
Xin lỗi, nhưng tôi không phải là người đang ca ngợi ở đây. Câu trả lời cho câu hỏi của bạn rất đơn giản: đóng dấu một lớp khi bạn không muốn hỗ trợ kế thừa. Đó là nó.
Robert Harvey

Câu trả lời:


27

Điều này không quá khó để hiểu. sealedđã được tạo ra ĐẶC BIỆT cho Microsoft để làm cho cuộc sống của họ dễ dàng hơn, tiết kiệm hàng tấn tiền và giúp danh tiếng của họ. Vì nó là một tính năng ngôn ngữ mà mọi người khác cũng có thể sử dụng nhưng BẠN có thể sẽ không bao giờ cần phải sử dụng niêm phong.

Hầu hết mọi người đang phàn nàn về việc không thể mở rộng một lớp và nếu họ làm như vậy thì họ nói tốt mọi người đều biết đó là trách nhiệm của các nhà phát triển để làm cho nó hoạt động chính xác. Điều đó là chính xác, NGOẠI TRỪ những người đó không có manh mối về lịch sử của Windows và một trong những vấn đề sealedđang cố gắng giải quyết.

Giả sử nhà phát triển đã mở rộng lớp lõi .Net (vì không được niêm phong) và khiến nó hoạt động hoàn hảo. Yay, cho nhà phát triển. Nhà phát triển cung cấp sản phẩm cho khách hàng. Ứng dụng của nhà phát triển hoạt động rất tốt. Khách hàng hài lòng. Cuộc sống là tốt.

Bây giờ Microsoft phát hành một hệ điều hành mới, bao gồm sửa các lỗi trong lớp lõi .Net cụ thể này. Khách hàng muốn theo kịp thời đại và chọn cài đặt hệ điều hành mới. Thật bất ngờ, ứng dụng mà khách hàng thích rất nhiều không còn hoạt động nữa, vì nó không tính đến các lỗi đã được sửa trong lớp lõi .Net.

Ai nhận lỗi?

Những người quen thuộc với lịch sử của Microsoft đều biết rằng HĐH mới của Microsoft sẽ bị khiển trách chứ không phải phần mềm ứng dụng đã lạm dụng các thư viện windows. Vì vậy, nó trở thành đương nhiệm của Microsoft để khắc phục vấn đề thay vì công ty ứng dụng đã tạo ra vấn đề. Đây là một trong những lý do tại sao mã Windows trở nên cồng kềnh. Từ những gì tôi đã đọc, mã hệ điều hành Windows nằm rải rác với if-then cụ thể kiểm tra xem một ứng dụng và phiên bản cụ thể có đang chạy hay không và nếu vậy thì hãy xử lý đặc biệt để cho phép chương trình hoạt động. Đó là rất nhiều tiền mà Microsoft đã bỏ ra để khắc phục sự bất tài của một công ty khác.

Sử dụng sealedkhông loại bỏ hoàn toàn kịch bản trên, nhưng nó có ích.


4
@Cawas Thật khó để lạm dụng nó. Eric Lippert đã tuyên bố trong một số trường hợp, ông mong muốn rằng các lớp, như các phương thức, sealedtheo mặc định, trừ khi không được tiết lộ cụ thể, đơn giản vì rất ít lớp được thiết kế để được kế thừa. Nhiều khả năng là lớp của bạn không được xây dựng để hỗ trợ nó và bạn nên đảm bảo rằng bạn đã dành thời gian dành cho nhà phát triển đó nếu bạn không muốn đánh dấu nó là không được bảo vệ.
Phục vụ

1
Tôi nghĩ rằng nếu mọi người đang sử dụng niêm phong cho phần mềm phát triển nội bộ của họ thì có lẽ họ đang lạm dụng nó hoặc chỉ đang lãng phí thời gian của công ty khi cố gắng quá hoàn hảo. Tôi nói có lẽ bởi vì luôn có những trường hợp mà người ta có thể nghĩ ra điều đó có ý nghĩa trong một số tình huống cụ thể. Tuy nhiên, đối với những người phát triển phần mềm kiểu thư viện, tôi sẽ nghi ngờ rằng nó rất hữu ích vì những lý do tương tự mà Microsoft quyết định cần có nó.
Dunk

2
@Cawas Phần lớn các lớp được viết bởi hầu hết các nhà phát triển sẽ không bao giờ cần phải được kế thừa và không được viết để hỗ trợ kế thừa. Điều này có thể được truyền tải nhanh chóng và hiệu quả tới người đọc / người dùng mã bằng cách tạo kiểu sealed. Nếu thực tế nó là tùy chọn mặc định thì điều đó có nghĩa là nếu ai đó được thừa hưởng từ một loại thì họ sẽ biết rằng nó được xây dựng để hỗ trợ nó.
Phục vụ

2
Không tiết lộ một lớp sẽ không có nghĩa là lớp được xây dựng để hỗ trợ nó. Nó chỉ có nghĩa là ai đó muốn thừa kế từ lớp và bỏ nó. Trong trường hợp tốt nhất, việc sử dụng niêm phong đơn giản sẽ khiến các nhà phát triển viết lại chức năng hiện có (tương đương với lớp niêm phong) nhưng thường thì không, nếu mã nguồn có sẵn, họ sẽ đơn giản bỏ qua nó mà không tính đến bất kỳ hậu quả nào. Việc niêm phong được đặc biệt và hiếm khi được thiết lập, sẽ tốt hơn bởi vì sau đó nhà phát triển có thể muốn tìm hiểu tại sao lớp này được niêm phong. Quá nhiều lớp niêm phong và họ sẽ không quan tâm tại sao.
Dunk

1
Ngoài ra bảo mật là một lý do để sử dụng nó! Hãy xem xét một ứng dụng hộp cát cố gắng truy cập một tập tin. Hộp cát có thể kiểm tra chuỗi tên tệp, nhưng nếu kẻ tấn công có thể gửi cho bạn một biến thể String và sau đó chúng biến đổi nó sau khi kiểm tra bảo mật nhưng trước I / O thì sao? Tôi tin rằng loại kịch bản là lý do tại sao Java Stringđược đánh dấu final(tương tự sealed) và tôi đặt cược cùng một logic làm cơ sở cho một số quyết định C #.
Darien

23

sealedđược sử dụng để chỉ ra rằng người viết của lớp đã không thiết kế nó để được kế thừa. Không hơn không kém

Thiết kế đúng một giao diện đã đủ khó đối với nhiều lập trình viên. Thiết kế đúng một lớp có thể được kế thừa có thêm độ khó và dòng mã. Nhiều dòng mã được viết có nghĩa là nhiều mã hơn để duy trì. Để tránh khó khăn ngày càng tăng này, sealedcó thể chỉ ra rằng lớp không bao giờ được dự định kế thừa và trong bối cảnh này, niêm phong một lớp là một giải pháp hoàn toàn hợp lệ cho một vấn đề .

Hãy tưởng tượng trường hợp mà lớp CustomBoeing787có nguồn gốc từ Airliner. Điều này CustomBoeing787ghi đè một số phương thức được bảo vệ từ Airliner, nhưng không phải tất cả chúng. Nếu nhà phát triển có đủ thời gian và nó xứng đáng, anh ta có thể kiểm tra lớp để đảm bảo mọi thứ hoạt động như mong đợi, ngay cả trong bối cảnh khi các phương thức không được ghi đè (ví dụ: các setters được bảo vệ thay đổi trạng thái của đối tượng). Nếu cùng một nhà phát triển (1) không có thời gian, (2) sẽ không muốn chi thêm hàng trăm hoặc hàng ngàn đô la cho ông chủ / khách hàng của mình hoặc (3) không muốn viết thêm mã mà anh ta không muốn viết cần ngay bây giờ (YAGNI), sau đó anh ta có thể:

  • hoặc phát hành mã trong tự nhiên, xem xét rằng đó là mối quan tâm của các lập trình viên, những người sẽ duy trì dự án này sau này để quan tâm đến các lỗi tiềm ẩn,

  • hoặc đánh dấu lớp sealedđể hiển thị rõ ràng cho các lập trình viên tương lai rằng lớp này không có ý định kế thừa, và việc tiết lộ nó và sử dụng nó như một phụ huynh nên tự chịu rủi ro.

Có phải là một ý tưởng tốt để đóng dấu càng nhiều lớp càng tốt, hoặc càng ít càng tốt? Từ kinh nghiệm của tôi, không có câu trả lời dứt khoát. Một số nhà phát triển có xu hướng sử dụng sealedquá nhiều; những người khác không quan tâm đến việc lớp học sẽ được kế thừa như thế nào và vấn đề nó có thể gây ra. Với cách sử dụng như vậy, vấn đề tương tự như vấn đề bao gồm việc xác định liệu lập trình viên có nên sử dụng hai hoặc bốn khoảng trắng để thụt lề hay không: không có câu trả lời đúng.


Được rồi ... Xin lỗi nếu tôi nghe có vẻ hung hăng một lần nữa, nhưng tôi chỉ muốn rõ ràng và quyết đoán ở đây ... Tôi chỉ có thể hiểu những gì bạn vừa viết theo một trong hai cách, nếu bạn muốn viết tl;drở đây. Đó là "Không, không có một lý do chính đáng nào" hoặc "Tôi nghĩ không có lý do chính đáng nào, nhưng tôi cũng không biết." . Đối với tôi "không có câu trả lời dứt khoát" là một trong số đó.
cregox

6
sealedđược sử dụng để chỉ ra rằng người viết của lớp đã không thiết kế nó để được kế thừa. Đó là lý do duy nhất của bạn.
Robert Harvey

Đó là một lý do tốt như cho bạn một chiếc xe đạp không có đèn và thực thi, bằng cách nào đó, bạn không thể thêm đèn.
cregox

2
@Cawas Làm sao vậy? Trong bối cảnh đó nó không phải là quan trọng đối với người xây dựng chiếc xe đạp để đảm bảo rằng chiếc xe đạp không có ánh sáng, nhưng nó thường quan trọng đối với người sử dụng của một loại để đảm bảo rằng việc thực hiện là một việc thực hiện chính xác cụ thể. Bạn thi hành các ràng buộc bạn cần. Trong một số trường hợp, mọi người có thể thêm một ràng buộc không thực sự cần thiết; bạn đã cung cấp một ví dụ về điều đó. Chỉ vì các ràng buộc được sử dụng sai ở một nơi không có nghĩa là bạn không bao giờ nên hạn chế bất cứ điều gì.
Phục vụ

1
Ngoài ra bảo mật là một lý do để sử dụng nó! Hãy xem xét một ứng dụng hộp cát cố gắng truy cập một tập tin. Hộp cát có thể kiểm tra chuỗi tên tệp, nhưng nếu kẻ tấn công có thể gửi cho bạn một biến thể String và sau đó chúng biến đổi nó sau khi kiểm tra bảo mật nhưng trước I / O thì sao? Tôi tin rằng loại kịch bản là lý do tại sao Java Stringđược đánh dấu final(tương tự sealed) và tôi đặt cược cùng một logic làm cơ sở cho một số quyết định C #.
Darien

4

Khi một lớp được niêm phong, nó cho phép mã sử dụng loại đó để biết chính xác những gì họ đang xử lý.

Bây giờ trong C # stringsealed, bạn không thể thừa hưởng từ nó, nhưng hãy giả sử trong một giây không phải vậy. Nếu bạn đã làm, thì ai đó có thể viết một lớp như thế này:

public class EvilString// : String
{
    public override string ToString()
    {
        throw new Exception("I'm mean");
    }
    public override bool Equals(object obj)
    {
        return false;
    }
    public override int GetHashCode()
    {
        return 0;
    }
}

Bây giờ đây sẽ là một lớp chuỗi vi phạm tất cả các loại thuộc tính mà các nhà thiết kế stringđã biết là đúng. Họ biết rằng Equalsphương pháp này sẽ mang tính bắc cầu, nhưng điều này thì không. Heck, phương thức bằng này thậm chí không đối xứng, vì một chuỗi có thể bằng với nó nhưng nó sẽ không bằng chuỗi đó. Tôi chắc chắn rằng có tất cả các loại lập trình viên đã viết mã theo giả định rằng ToStringphương pháp stringsẽ không đưa ra một ngoại lệ cho các giá trị khác không. Bây giờ bạn sẽ có thể vi phạm giả định đó.

Có bất kỳ số lượng các lớp khác chúng ta có thể làm điều này cho, và tất cả các loại giả định khác mà chúng ta có thể vi phạm. Nếu bạn loại bỏ tính năng ngôn ngữ chosealedsau đó các nhà thiết kế ngôn ngữ bây giờ cần bắt đầu hạch toán những thứ như thế này trong tất cả các mã thư viện của họ. Họ cần thực hiện tất cả các loại kiểm tra để đảm bảo rằng các loại mở rộng của loại mà họ muốn sử dụng sẽ được viết "đúng", đây có thể là một việc rất tốn kém (cả về thời gian phát triển, cũng như thời gian chạy). Bằng cách có thể niêm phong một lớp, họ có thể đảm bảo rằng điều này là không thể, và bất kỳ xác nhận nào họ đưa ra về các chi tiết triển khai của các loại của riêng họ đều không thể bị vi phạm, ngoại trừ các loại được thiết kế có chủ ý được mở rộng. Đối với những loại được thiết kế để mở rộng, bạn sẽ thấy mã ngôn ngữ cần phải phòng thủ hơn nhiều về cách nó xử lý chúng.


Nhưng bạn có thể vi phạm giả định đó trong mã của bạn . Không giống như bạn đang lấy nguồn của String và chỉnh sửa nó. Các nhà thiết kế sẽ không cần phải tính đến điều này bởi vì đó là 1 lá, 1 nhánh, 1 khách hàng sử dụng nó với rủi ro và quyết định riêng của mình. Nó sẽ không phổ biến từ đó, trừ khi các khách hàng khác thích làm như vậy. Và như thế.
cregox

3
@Cawas Và nếu một ngoại lệ bị ném vào một thời điểm không mong muốn và kết quả là tài nguyên bị rò rỉ, hoặc một lớp bị bỏ lại trong trạng thái không xác định và các chức năng không phù hợp? Trường hợp này hơi ngớ ngẩn, nhưng nó có thể dễ dàng là trường hợp ai đó viết một triển khai mà họ cho là hợp lý, nhưng đôi khi ném khi không nên hoặc không hoạt động với các giá trị nhất định. Sau đó, họ sẽ khiếu nại khi mã ngôn ngữ không hoạt động. Tốt hơn hết là đừng để mọi người làm những việc mà ngôn ngữ sẽ không thể hỗ trợ.
Phục vụ

Trong mọi trường hợp, bạn đang nói về việc xây dựng một trình biên dịch. Có nhiều sealedtính năng như vậy được tích hợp sẵn mà chúng tôi không sử dụng. Nó vẫn không giải thích tại sao sử dụng nó bên ngoài phạm vi hẹp như vậy và, hẹp như mã trình biên dịch , thậm chí không giải thích được sealedsự tồn tại.
cregox

2
@Cawas stringLoại không phải là trình biên dịch mã. Đó là một phần của mã ngôn ngữ. Hoàn toàn khác nhau. Trong mọi trường hợp, tôi chỉ chọn một ví dụ. Bạn có thể chọn hầu hết các lớp niêm phong trong toàn bộ BCL và sử dụng nó làm ví dụ.
Phục vụ

4
@Cawas: Tôi nghĩ những gì bạn có thể thiếu ở đây là khía cạnh hỗ trợ khách hàng. Nếu bạn cho phép một lớp được kế thừa, khách hàng sẽ được thừa hưởng từ nó, và sau đó họ sẽ gọi cho bạn khi nó tan vỡ. Bạn có thể nói với họ cả ngày rằng họ thừa hưởng từ lớp đó có nguy cơ, nhưng bạn vẫn sẽ nhận được cuộc gọi, vì bạn cho phép họ thừa kế từ đó, vì vậy họ cho rằng an toàn khi làm như vậy.
Robert Harvey

3

Có bất kỳ lý do tốt để sử dụng niêm phong?

Tăng cường? Không thường xuyên. Tôi sẽ chỉ sử dụng niêm phong khi tôi có một loại không thay đổi (hoặc một số hạn chế khác) thực sự cần duy trì bất biến tôi không thể tin tưởng những người thừa kế vào yêu cầu đó mà không đưa các lỗi catastropic tinh vi vào hệ thống.

Giả sử có một lý do chính đáng để sử dụng niêm phong và chúng ta nên sử dụng nó làm mặc định cho mọi thứ, chúng ta làm gì với thừa kế?

Chúng tôi sử dụng sự kế thừa cho những thứ không mặc định. Ngay cả khi thành phần được ưa chuộng hơn sự kế thừa (và thực tế), điều đó không có nghĩa là sự kế thừa sẽ bị loại bỏ. Điều đó có nghĩa là sự kế thừa có một số vấn đề nội tại mà nó đưa vào thiết kế và khả năng duy trì mã và thành phần thực hiện nhiều điều tương tự với (nói chung) ít vấn đề hơn. nó có nghĩa là ngay cả khi thành phần được ưa chuộng thì sự kế thừa là tốt cho các tập hợp con nhất định của các vấn đề.

Tôi không có nghĩa là quá có ý nghĩa nhưng nếu bạn vừa nghe nói về RẮN và thử nghiệm đơn vị, có lẽ bạn nên thoát ra khỏi hòn đá của mình và thực sự viết mã. Mọi thứ không rõ ràng và hiếm khi "luôn luôn làm X" hoặc "không bao giờ sử dụng Y" hoặc "Z là tốt nhất" là cách đúng đắn (giống như bạn có vẻ hấp dẫn dựa trên quan điểm của câu hỏi của bạn). Khi bạn viết mã, bạn có thể thấy các trường hợp sealedcó thể tốt và các trường hợp khiến nó đau buồn - giống như bất kỳ sự đánh đổi nào khác.


Đối với tôi, điều này và "để tránh phải hỗ trợ thừa kế cho khách hàng" mà Robert không muốn giải thích là những câu trả lời hứa hẹn nhất ... Có lẽ bạn có thể giải thích thêm về những trường hợp bạn sử dụng sealed, làm ơn?
cregox

@Cawas - Tôi không chắc mình có thể làm tốt. Tôi rất hiếm khi làm điều đó và nó thường là một sự đánh đổi trong đó đảm bảo rằng một cái gì đó không thay đổi (để tối ưu hóa hiệu suất, đơn giản hóa thiết kế) đáng để không thể kế thừa từ đối tượng.
Telastyn

Thật tuyệt. Dunk đã nhúng nó! : P Cảm ơn rất nhiều vì câu trả lời. Và bạn là người duy nhất nhận được "gợi ý tinh tế" về chuyên môn của tôi. Có vẻ như mọi người cho rằng tôi biết nhiều hơn, tôi không biết ... Nhưng tôi ước "chỉ cần mã hóa" sẽ đưa tôi ra khỏi tảng đá này. Có lẽ tôi áp dụng những khái niệm đó theo một cách nào đó, chỉ là không cần thủ tục như tôi có thể nên làm.
cregox

3

Trước hết, bạn nên đọc bài đăng của Eric Lippert về lý do tại sao Microsoft niêm phong các lớp học của họ.

http://bloss.msdn.com/b/ericlippert/archive/2004/01/22/61804.aspx

Thứ hai, từ khóa kín tồn tại để làm chính xác những gì nó làm - ngăn chặn sự kế thừa. Có nhiều tình huống mà bạn muốn ngăn chặn sự kế thừa. Hãy xem xét một lớp học mà bạn có một bộ sưu tập. Nếu mã của bạn phụ thuộc vào lớp đó hoạt động theo kiểu cụ thể, bạn không muốn ai đó ghi đè một trong các phương thức hoặc thuộc tính trong lớp đó và khiến ứng dụng của bạn bị lỗi.

Thứ ba, sử dụng niêm phong khuyến khích thành phần trên thừa kế, đó là một thói quen tốt để có được vào. Sử dụng thành phần trên thừa kế có nghĩa là bạn không thể phá vỡ nguyên tắc thay thế của Liskov và bạn đang tuân theo nguyên tắc Mở / Đóng. sealeddo đó là một từ khóa hỗ trợ bạn tuân theo hai trong số năm nguyên tắc quan trọng nhất của lập trình oo. Tôi muốn nói rằng làm cho nó một tính năng rất có giá trị.


Phần đầu tiên đã được chỉ ra trong các ý kiến ​​câu hỏi. Phần thứ hai chỉ là lý luận nhiều hơn mà không có nguyên nhân thực sự. Phần thứ ba, mặc dù đã được tiếp cận ở nơi khác, có thể có một cái gì đó cho nó. Tôi sẽ tập trung vào cái đó.
cregox

điểm thứ ba không khuyến khích thành phần hơn thừa kế, nó loại bỏ hoàn toàn quyền thừa kế như một tùy chọn, ngay cả khi đó là lựa chọn tổng thể tốt nhất.
Michael Shaw

Điều đó phụ thuộc vào việc bạn có kiểm soát codebase hay không. Nếu bạn đóng dấu các lớp, bạn luôn có thể bỏ niêm phong chúng sau này nếu cần.
Stephen

2

Tôi nghĩ rằng câu hỏi này không có câu trả lời khách quan và tất cả phụ thuộc vào quan điểm của bạn.

Một bên, một số người muốn mọi thứ "mở" và gánh nặng đảm bảo mọi thứ hoạt động chính xác là ở người mở rộng lớp học. Đây là lý do tại sao các lớp được mở để kế thừa theo mặc định. Và tại sao các phương thức Java đều là ảo theo mặc định.

Mặt khác, một số người muốn mọi thứ được đóng theo mặc định và cung cấp các tùy chọn để mở nó. Trong trường hợp này, tác giả của lớp cơ sở, người cần đảm bảo mọi thứ anh ta làm "mở" đều an toàn để sử dụng theo bất kỳ cách nào có thể tưởng tượng được. Đây là lý do tại sao trong C #, tất cả các phương thức đều không ảo theo mặc định và cần được khai báo ảo để được ghi đè. Nó cũng dành cho những người đó, đó là cách để tránh các mặc định "mở". Giống như làm cho lớp bị niêm phong / cuối cùng, bởi vì họ thấy ai đó xuất phát từ lớp là một vấn đề lớn đối với thiết kế của lớp họ.


Như thế này thì giống hơn đấy! Đây có thể là một lý do tốt ... "Bởi vì mọi người muốn đóng nó". Và đó cũng là điều tôi đang cố gắng nói trong câu hỏi: có vẻ như các lớp không ảo trong C ++ có thể bị ghi đè. sealedkhông thể Làm thế nào chúng ta có thể thừa hưởng từ họ? Tất cả những gì tôi đọc là chúng ta không thể. Không bao giờ. Tôi không biết. Tôi đã qua lại về chủ đề này được 4 tháng rồi, kể từ lần đầu tiên tôi nghe về việc niêm phong. Và tôi vẫn không biết làm thế nào cho đúng khi tôi cần sửa đổi bất cứ điều gì trên một lớp kín. Vì vậy, tôi thấy không có "tùy chọn để mở"!
cregox

4
Đây không phải là lý do tại sao các phương thức lớp C ++ không ảo theo mặc định. Tạo một phương thức ảo có nghĩa là phải có thêm chi phí trên bảng tra cứu phương thức và C ++ có triết lý là bạn chỉ trả tiền cho chi phí khi bạn muốn tính năng này.
Michael Shaw

@Ptolemy Ok, tôi gỡ nó ra. Tôi không bao giờ nên viết nó, bởi vì tôi biết mọi người bắt đầu phàn nàn về nó.
Euphoric

này, tôi hoàn toàn đánh giá cao rằng nếu bạn muốn tuyên bố rằng mọi người muốn viết các lớp đóng theo mặc định và phải chủ động chọn mở chúng thì bạn sẽ phải nắm chặt ống hút
Michael Shaw

IMO nó rất giống với các cuộc tranh luận riêng tư / được bảo vệ / công khai khi nói về API: Nó phụ thuộc rất nhiều vào người kiểm soát lớp, ai muốn kế thừa lớp, giao tiếp giữa hai người và tần suất xuất hiện các phiên bản mới.
Darien

-2

vấn đề với niêm phong trong C # là nó khá cuối cùng. Trong 7 năm phát triển thương mại C #, nơi duy nhất tôi thấy nó được sử dụng là trên các lớp Microsoft .NET, nơi tôi cảm thấy mình có lý do chính đáng để mở rộng một lớp khung để thực hiện hành vi được điều chỉnh và vì lớp này đã bị niêm phong, tôi không thể .

Không thể viết một lớp suy nghĩ về mọi cách có thể được sử dụng, và quyết định rằng không ai trong số chúng là hợp pháp. Tương tự như vậy nếu bảo mật khung phụ thuộc vào lớp không được kế thừa, thì bạn có một lỗi thiết kế bảo mật.

Vì vậy, kết luận, tôi chắc chắn về quan điểm rằng niêm phong không phục vụ mục đích hữu ích và cho đến nay tôi chưa đọc được gì ở đây đã thay đổi quan điểm đó.

Tôi có thể thấy cho đến nay đã có ba đối số biện minh được niêm phong cho đến nay.

  1. Luận điểm 1 là nó loại bỏ một nguồn lỗi khi mọi người thừa hưởng từ các lớp và sau đó đã tăng quyền truy cập vào các phần bên trong của lớp đó mà không thực sự hiểu đúng về các phần bên trong.

  2. Đối số 2 là nếu bạn mở rộng một lớp microsoft và sau đó microsoft thực hiện sửa lỗi trong lớp đó nhưng sự gia hạn của bạn dựa vào lỗi đó thì mã của bạn đã bị hỏng, microsoft bị đổ lỗi và bịt kín ngăn chặn điều đó

  3. Đối số 3 là với tư cách là nhà phát triển của lớp, lựa chọn của tôi có cho phép bạn mở rộng nó hay không, như là một phần trong thiết kế của lớp tôi.

Đối số 1 dường như là một đối số mà bạn lập trình viên cuối không biết cách sử dụng mã của tôi. Đó có thể là trường hợp, nhưng nếu bạn vẫn cho phép tôi truy cập vào giao diện đối tượng thì vẫn đúng là tôi đang sử dụng đối tượng của bạn và thực hiện các cuộc gọi đến nó mà không hiểu cách sử dụng nó, và do đó có thể gây ra nhiều thiệt hại theo cách đó . Đây là một lời biện minh yếu ớt về sự cần thiết phải niêm phong.

Tôi hiểu cơ sở thực tế cho arg 2 đến từ đâu. Đặc biệt, khi microsoft đưa các kiểm tra hệ điều hành bổ sung vào các cuộc gọi api win32 để xác định các cuộc gọi không đúng định dạng, điều này đã cải thiện tính ổn định chung của Windows XP so với Windows NT, nhưng với chi phí ngắn hạn, nhiều ứng dụng đã bị hỏng khi Windows XP được phát hành. Microsoft đã giải quyết vấn đề này bằng cách đặt 'quy tắc' cho các kiểm tra này để nói, bỏ qua khi ứng dụng X phá vỡ quy tắc này, đây là một lỗi đã biết

Đối số 2 là một đối số kém vì được niêm phong tốt nhất không có gì khác biệt bởi vì nếu có lỗi trong thư viện .NET, bạn không có lựa chọn nào khác ngoài việc tìm một công việc xung quanh và khi sửa lỗi microsoft xuất hiện, rất có khả năng có nghĩa là công việc của bạn xung quanh phụ thuộc vào hành vi bị hỏng bây giờ bị phá vỡ. Cho dù bạn đã khắc phục điều này bằng cách sử dụng tính kế thừa hoặc bằng một số mã trình bao bọc bổ sung khác, khi mã được sửa, công việc của bạn sẽ bị hỏng.

Đối số 3 là đối số duy nhất có bất kỳ chất nào để tự biện minh cho chính nó. Nhưng nó vẫn còn yếu. Nó chỉ đi ngược lại với hạt tái sử dụng mã.


2
/ tôi gửi email đến microsoft, xin vui lòng bạn có thể hủy bỏ lớp X cho tôi và gửi bản phát hành .NET mới. Trân trọng, .... Như tôi đã nói, lần duy nhất trong phát triển thương mại tôi đã thấy một lớp niêm phong, không thể bỏ qua nó.
Michael Shaw

6
It is impossible to write a class thinking about every possible way it could be used- Đó chính xác là lý do nhiều lớp Framework bị niêm phong ... Nó giúp loại bỏ nhu cầu suy nghĩ về mọi cách có thể mà ai đó có thể mở rộng lớp.
Robert Harvey

5
Nếu bạn có thể mở nó ra, sẽ không có nhiều điểm trong việc niêm phong nó, phải không?
Robert Harvey

2
@Ptolemy Cho phép mọi người mở rộng lớp học của bạn là một tính năng . Một trong đó tiêu thụ một lượng đáng kể nỗ lực phát triển. Đây là một tính năng chỉ đáng để chứng minh nếu tác giả của lớp có thể thấy đủ lợi ích trong các tiện ích mở rộng tiềm năng để biện minh cho nỗ lực này. Nếu họ không thể chứng minh nỗ lực, và do đó loại và người dùng của nó không được xây dựng để hỗ trợ tiện ích mở rộng, thì điều quan trọng là phải ngăn chặn nó, nếu không, bạn có thể mở rộng loại kỹ thuật, nhưng không thể hoạt động đúng khi bạn làm như vậy
Phục vụ

2
@Cawas: Bạn đang gặp khó khăn.
Robert Harvey


-8

Bằng chứng là câu hỏi của tôi, tôi không có chuyên gia ở đây. Nhưng tôi thấy không có lý do gì sealedđể tồn tại.

Nó dường như được thực hiện để giúp các kiến ​​trúc sư mã để thiết kế một giao diện. Nếu bạn muốn viết một lớp sẽ ra ngoài tự nhiên và nhiều người sẽ thừa hưởng từ nó, sửa đổi bất cứ điều gì trong lớp đó có thể phá vỡ nó cho quá nhiều người. Vì vậy, chúng tôi có thể niêm phong nó và không ai có thể thừa kế. "Vấn đề được giải quyết".

Chà, có vẻ như "che một chỗ và phát hiện ra một điểm khác". Và nó thậm chí không giải quyết được vấn đề - nó chỉ loại bỏ một công cụ : thừa kế. Là bất kỳ công cụ nào, nó có nhiều công dụng và kế thừa từ một lớp không ổn định là rủi ro bạn gặp phải. Ai chấp nhận rủi ro đó thì nên biết rõ hơn.

Có lẽ có thể có một từ khóa stable, vì vậy mọi người sẽ biết rằng an toàn hơn khi kế thừa từ đó.


2
"Giải quyết vấn đề" - Chính xác.
Robert Harvey

@RobertHarvey Nó không được giải quyết, như được giải thích ngay trong đoạn tiếp theo.
cregox

8
Bạn đang điên vì bạn không thể mở rộng lớp học. Điều đó không có nghĩa là đó sealedkhông phải là một công cụ hữu ích cho các nhà thiết kế khung. Các lớp trong một khung nên là hộp đen; bạn không cần phải biết về nội bộ của một lớp để có thể sử dụng nó đúng cách. Tuy nhiên, đó chính xác là những gì thừa kế đòi hỏi.
Robert Harvey

Tôi chưa bao giờ nói nó không hữu ích. Tôi nói tôi không thấy cách sử dụng của nó, và chỉ ra lý do tại sao. Xin vui lòng, tôi đang cầu xin bạn, cho tôi một lý do tốt để sử dụng nó! Ngay cả khi đó chỉ là "vì tôi muốn theo một mẫu thiết kế khép kín", điều đó vẫn ổn. Tôi không thấy ai đưa ra lý do đó, rõ ràng.
cregox

7
Lý do chính đáng là bạn không phải hỗ trợ thừa kế trên một lớp kín.
Robert Harvey
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.