You can just used tagged enums and the inline else syntax, like this:
const Animal = union(enum) {
cat: Cat,
dog: Dog,
pub fn make_noise(self: Animal) void {
switch (self) {
inline else => |impl| impl.make_noise(),
}
}
};