2012-02-05 15 views
5

Tôi gặp sự cố khi thiết kế ứng dụng D. Có lẽ cách tiếp cận của tôi là hoàn toàn sai, vì vậy tôi đến đây để bạn giải cứu tôi. Bất kỳ đề xuất nào, bao gồm viết lại hoàn toàn, đều được chào đón.Xử lý D cấu trúc khuôn mẫu như một loại phổ biến

Tôi có một số loại templated:

enum Type : byte { Message='!', Integer='@' } 

struct Token (T) { 
    Type type; 
    T value; 
} 

alias Token!string MessageToken; 
alias Token!long IntegerToken; 

Và tôi cần phải xử lý các loại tổng quát:

AnyToken genToken(bool cond) { 
    if (cond) 
    return MessageToken(Type.Message, "nighly builds"); 
    else 
     return IntegerToken(Type.Integer, -42); 
} 

AnyToken a = genToken(true); 
AnyToken b = genToken(false); 

Làm thế nào để đạt được hiệu ứng này? Chỉnh sửa: Lựa chọn thay thế OOP cũng được hoan nghênh.

Trả lời

6

tôi đã sử dụng một sự kết hợp gắn thẻ chính mình

struct Token{ 
    Type type; 
    union{ 
     string str; 
     long integer; 
    } 
    @property string strMessage()in{assert(type==Type.Message)}body{ 
     return str; 
    } 
    @property void strMessage(string s){ 
     type=Type.Message; 
     str=s; 
    } 
    @property long intMessage()in{assert(type==Type.Integer)}body{ 
     return integer; 
    } 
    @property void intMessage(long l){ 
     type=Type.Integer; 
     integer=l; 
    } 
} 

lưu ý rằng không có tĩnh (thời gian biên dịch) khác biệt giữa chúng nhưng nó khá nhiều là tốt nhất về thể làm mà không thừa kế

bạn có thể thêm một số chức năng phụ để nó trông giống như thừa kế, do đó bạn sẽ không cần phải kiểm tra trường kiểu quá bên ngoài các hàm của cấu trúc

+0

Làm cách nào để thêm các chức năng cho nó trông giống như thừa kế? Ít thi sẽ tốt hơn. Tôi thích cách bạn suy ra loại từ đối số, phù hợp tốt ở đây. –

+1

bên trong hàm bạn có thể thực hiện lệnh 'final switch (type) {case Type.Integer: ... case Type.Message: ...}' trong hàm. Tôi có nghĩa rằng (hầu hết) những kiểm tra sẽ được tập trung bên trong định nghĩa của cấu trúc để khi bạn muốn thêm một loại bạn sẽ không phải săn tất cả xuống –

+0

Cảm ơn, bây giờ tôi đang sử dụng 'final switch' cho nó. –

4

Bạn có thể sử dụng std.variant.

Tôi không thể tưởng tượng một cách khác. Cuối cùng, chúng là các loại hoàn toàn riêng biệt.

+1

Tôi có một số lợi thế trong việc sử dụng 'std.variant' thay vì xây dựng liên minh được gắn thẻ của riêng tôi không? –

2

Nếu bạn thực sự cần giữ cấu trúc ban đầu thì bạn có thể tạo phân cấp các lớp bọc con trỏ cho một cấu trúc và công văn phù hợp.

+0

Không, tôi không cần giữ cấu trúc. Điều gì về một hệ thống phân cấp lớp bao gồm một liên minh được bảo vệ? Sẽ có _many_ mã thông báo nhỏ có ít hoặc không có bản sao. –

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