Crystal has Interfaces in Java sense

During discussion we’ve discovered Crystal has interfaces in Java sense.

Module can have abstract method, and its inclusion demands implementation:
https://play.crystal-lang.org/#/r/e1jl

module Moo
  abstract def size : Int
end
 
struct Fix
  include Moo
end
# Error: abstract `def Moo#size()` must be implemented by Fix

Containers could be specialized to modules, function/method could have argument restricted to module, and their call is correctly polymorphic:
https://play.crystal-lang.org/#/r/e1jq

module Moo
  abstract def size : Int
end
 
class Fix2
  include Moo
  def size : Int; 2; end
end
 
class Fix3
  include Moo
  def size : Int; 3; end
end
 
def say(s : Moo)
  puts "size is #{s.size}"
end
 
say Fix2.new
say Fix3.new
moos = Array(Moo){Fix2.new, Fix3.new}
moos.each{|f| say f}
[Fix2.new, Fix3.new].each{|f| say f}
# size is 2
# size is 3
# size is 2
# size is 3
# size is 2
# size is 3
1 Like

I think it should be mentioned in tutorial/reference.

2 Likes

Related Github discussion Go Language like interfaces? · Issue #3489 · crystal-lang/crystal · GitHub

Yeah, I suppose this specific use case should be explicit on Modules - Crystal

Currently there is just this sentence at the end of Virtual and abstract types - Crystal

Abstract methods can also be defined in modules, and the compiler will check that including types implement them.

Here’s some “Structural” interface typing: almost as in Go, but with explicit interface initiation
https://play.crystal-lang.org/#/r/e1rt

Generator for wrapped methods should be extended for splat, kwargs and block.
And I don’t know how to properly hide Wrapper from occasional usage.
But otherwise looks promising.

And a bit “improved” version (ie with macro “interface”)