zig实现builder模式

说明

rust在实现builder模式的时候,可以直接通过过程宏,直接通过修改token流,自动实现Builder类,同样的,zig也可以通过其特有的comptime生成Builder类。

代码实现

实现一个简单的泛型函数,接受需要实现Bulider类的type,返回对应的Builder类。

const std = @import("std");

/// A generic builder that constructs a value of type T step by step
pub fn Builder(comptime T: type) type {
    return struct {
        value: T = std.mem.zeroes(T),

        const Self = @This();

        /// Initialize the builder with default values
        pub fn init() Self {
            return .{};
        }

        /// Set a field by name and value
        pub fn set(self: *Self, comptime field: []const u8, value: anytype) *Self {
            if (!@hasField(T, field)) {
                @compileError(std.fmt.comptimePrint("Type {s} has no field named '{s}'", .{ @typeName(T), field }));
            }

            const field_type = @TypeOf(@field(self.value, field));
            if (@TypeOf(value) != field_type) {
                @compileError(std.fmt.comptimePrint("Expected type {s} for field '{s}', got {s}", .{
                    @typeName(field_type),
                    field,
                    @typeName(@TypeOf(value)),
                }));
            }

            @field(self.value, field) = value;
            return self;
        }

        /// Build and return the final value
        pub fn build(self: *const Self) T {
            return self.value;
        }
    };
}

// Example usage:
const Person = struct {
    name: []const u8 = "",
    age: u8 = 0,
    active: bool = false,
};

test "Builder example" {
    var person_builder = Builder(Person){};
    const name: []const u8 = "Alice";
    _ = person_builder.set("name", name).set("age", @as(u8, 30)).set("active", true);
    const person = person_builder.build();

    try std.testing.expectEqualStrings("Alice", person.name);
    try std.testing.expectEqual(@as(u8, 30), person.age);
    try std.testing.expect(person.active);
}

test "Builder with default values" {
    var person_builder = Builder(Person){};
    const name: []const u8 = "Bob";
    _ = person_builder.set("name", name);
    const person = person_builder.build();

    try std.testing.expectEqualStrings("Bob", person.name);
    try std.testing.expectEqual(@as(u8, 0), person.age); // default value
    try std.testing.expect(!person.active); // default value
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容