Zig: Interface

const std = @import("std");
const Io = std.Io;

pub fn main(_: std.process.Init) !void {
    const abby: Pet = .init("Abby");
    printName(&abby.named);
}

fn printName(n: *const Named) void {
    std.debug.print("The name is {s}.\n", .{n.name()});
}

const Pet = struct {
    pet_name: []const u8,
    named: Named,

    pub fn init(pet_name: []const u8) Pet {
        return .{
            .pet_name = pet_name,
            .named = .init(name),
        };
    }

    fn name(n: *const Named) []const u8 {
        return pet(n).pet_name;
    }

    fn pet(n: *const Named) *const Pet {
        return @alignCast(@fieldParentPtr("named", n));
    }
};

const Named = struct {
    vtable: VTable,

    pub fn init(name_fn: *const fn (n: *const Named) []const u8) Named {
        return .{ .vtable = .{ .name = name_fn } };
    }

    pub const VTable = struct {
        name: *const fn (n: *const Named) []const u8,
    };

    pub fn name(n: *const Named) []const u8 {
        return n.vtable.name(n);
    }
};