Search code examples
metaprogrammingcrystal-lang

Crystal : class warp or extension methods like CSharp


I exported a struct from a C library which is Void*

lib LibXXX
    alias OldStruct = Pointer(Void)
    fun foo(old : OldStruct)
end

And want to add some methods to LibXXX::Old

I know it's can only be done by a class warp in most language :

struct NewStruct {
    OldStruct old;
    void new_functions();
};

But it's really bothering that I must access field old explicitly. LibXXX.foo(old.old)

I want some transparent way keeping simple representation LibXXX.foo(old), like Inheritance or Extension Methods in CSharp.

I tried :

struct NewStruct < LibXXX::Old
# ...
end

But an compilation error occured:

can't extend non-abstract struct Pointer(Void)

I believe it must could be done using Crystal. But I don't know what's the best practice, so, please.


Solution

  • The best practice is to have a non-lib wrapper around your object, that wraps all of the existing methods. That's then often a good place to add your new functionality too or any idiomatic abstractions.

    lib LibPet
      alias Pet = Void*
      alias Dog = Void*
    
      fun make_dog : Dog
      fun bark(bar : Dog)
      fun move(pet : Pet)
      fun retreat(pet : Pet)
    end
    
    struct Dog
      def initialize
        @dog = LibPet.make_dog
      end
    
      def bark
        LibPet.bark(@dog)
      end
    
      def move
        LibPet.move(@dog)
      end
    
      def retreat
        LibPet.retreat(@dog)
      end
    
      def at_front
        move
        yield
      ensure
        retreat
      end
    
      def attack
        at_front { bark }
      end
    end