Có phải là xấu khi tạo các lớp mà mục đích duy nhất của nó là được chuyển đổi sang lớp khác không?


10

Hãy tưởng tượng một tình huống trong đó chúng ta đang sử dụng một thư viện cho phép bạn tạo Circlecác đối tượng, nơi bạn có thể chỉ định bán kính và tâm của vòng tròn để xác định nó. Tuy nhiên, vì một số lý do, nó cũng cần một flavourtham số bắt buộc . Bây giờ hãy nói rằng tôi thực sự cần sử dụng Circletrong ứng dụng của riêng mình, nhưng với mục đích của ứng dụng, tôi có thể đặt hương vị Flavours.Cardboardmỗi lần.

Để "giải quyết" điều này, tôi tạo Circlelớp riêng của mình trong một không gian tên khác, chỉ lấy radiuscenterlàm tham số, nhưng có một trình chuyển đổi ngầm định sang Circlelớp của thư viện bên ngoài chỉ tạo một Circle(this.radius, this.center, Flavours.Cardboard)đối tượng. Vì vậy, ở mọi nơi tôi cần loại khác Circle, tôi để chuyển đổi tự động diễn ra.

Hậu quả của việc tạo ra một lớp như vậy là gì? Có giải pháp nào tốt hơn không? Nó có khác biệt gì không nếu ứng dụng của tôi là một API được xây dựng trên đầu thư viện bên ngoài này, được các lập trình viên khác sử dụng?


Đây có vẻ như là một biến thể của Mẫu bộ điều hợp , mặc dù nó có vẻ có giá trị đáng ngờ ở đây (nó chỉ đơn thuần là sự tiện lợi để tránh đặt tham số).
Robert Harvey

5
Tại sao không tạo ra một MakeCircle chức năng ?
dùng253751

1
@immibis Thay là suy nghĩ đầu tiên của tôi. Khi tôi tạo trò chơi, tôi thường tạo một hàm theo các dòng của makePlayerchính nó chỉ chấp nhận các hợp đồng để đặt người chơi vào, nhưng giao cho một nhà xây dựng phức tạp hơn nhiều.
Carcigenicate

Câu trả lời:


13

Mặc dù không phải lúc nào cũng xấu, nhưng rất hiếm khi chuyển đổi ngầm là lựa chọn tốt nhất của bạn.

Có vấn đề.

  1. Chuyển đổi ngầm định không dễ đọc lắm.
  2. Bởi vì bạn đang tạo một đối tượng mới, bất kỳ thay đổi nào đối với đối tượng ban đầu sẽ không được nhìn thấy bởi đối tượng bạn đang chuyển đổi, dẫn đến lỗi.
  3. Nếu bạn đang ném đồ vật đi, đó là thêm rác để dọn dẹp.
  4. Nếu có sự cố, nó sẽ xảy ra khi chuyển đổi xảy ra, không phải khi sự việc được tạo, tạo ra các lỗi khó theo dõi hơn.

Nói chung, có những giải pháp tốt hơn.

  1. Tạo lớp bao bọc mỏng của riêng bạn, sử dụng lớp / khung khác trong nội bộ.
  2. Tạo một phương thức trợ giúp lấy các đối số của bộ dẫn mà bạn muốn và cung cấp một đối số đã được sửa, trả về đối tượng thực mà không phải chỉ định đối số bạn không quan tâm.
  3. Kế thừa từ lớp vấn đề và cung cấp hàm tạo đẹp hơn của riêng bạn.
  4. Nhận ra rằng việc thông qua tranh luận thêm thực sự không phải là vấn đề lớn.

Cá nhân, tôi thấy # 2 là đơn giản nhất để thực hiện và ít gánh nặng nhất trong thiết kế. Những người khác có thể ổn, với tình huống và những gì khác bạn đang cố gắng làm với các lớp này.

Chuyển đổi ngầm là giải pháp cuối cùng và chỉ thực sự có giá trị đối với tôi khi tôi có các hàm xử lý kiểu C ++ mà tôi đang cố gắng thực hiện - các đối tượng chiến lược mà tôi hoàn toàn chuyển đổi thành các loại ủy nhiệm.


1

Đưa ra kịch bản mà bạn đang mô tả, bạn có thể nghĩ về điều này theo ứng dụng chức năng một phần.

Hàm tạo là một hàm (ít nhất là trên lý thuyết; trong C #, bạn có thể tạo một "hàm xuất xưởng" gọi hàm tạo):

Func<double, Point, Flavour, Circle> MakeCircle = (r, p, f) => new Circle(r, p, f);

cho một phần ứng dụng, những điều sau đây sẽ đủ:

public static Func<T1, T2, R> Partial<T1, T2, T3, R>(this Func<T1, T2, T3, R> func, T3 t3)
   => (t1, t2) => func(t1, t2, t3);

Bây giờ bạn có thể nhận được hàm tạo của mình chỉ yêu cầu 2 tham số:

Func<double, Point, Circle> MakeCardboardCircle = Circle.Partial(Flavours.Cardboard)

Vì vậy, bây giờ bạn có một chức năng nhà máy với các tham số mong muốn của bạn

Circle c = MakeCardboardCircle(1.0, new Point(0, 0)))

BTW, điều này rõ ràng tương đương với tùy chọn 2 ở trên, chỉ từ góc độ chức năng hơn.

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.