I’m implementing an abstract HTTP rescuer handler:
require "http/server"
abstract class Rescuer(T)
include HTTP::Handler
def call(context)
call_next(context)
rescue error : T
handle(error)
end
# Bug: https://github.com/crystal-lang/crystal/issues/6762
def handle(error : T)
{% raise "Must be implemented" %}
end
end
class BasicRescuer(T) < Rescuer(T)
def handle(error : T)
puts error.inspect_with_backtrace
end
end
server = HTTP::Server.new([BasicRescuer(Exception).new]) do |context|
context.response.print("Hello\n")
end
server.bind_tcp(5000)
puts "Listening"
server.listen
Unfortunately, I’m getting this compile-time error:
in rescuer.cr:8: T is not a subclass of Exception
rescue error : T
require "http/server"
module Rescuer(T)
include HTTP::Handler
def call(context)
call_next(context)
rescue error : T
handle(error)
end
abstract def handle(error : T)
end
class BasicRescuer(T)
include Rescuer(T)
def handle(error : T)
puts error.inspect_with_backtrace
end
end
server = HTTP::Server.new([BasicRescuer(Exception).new]) do |context|
context.response.print("Hello\n")
end
Anyway, I think it’s a good practice to avoid inheritance like pest. More I develop, and less I think inheritance is useful, when you have great composition tools instead (include & extend)
That’s true exotic construction may sometime trigger error in the compiler.
However on your two examples, no offense but I think you try to bend Crystal where you should not.
Crystal is not a language offering reflection at runtime like Java or Ruby. And it would / should not anyway. Storing classes objects for example sounds like an anti-pattern for me. Because basically in Crystal you won’t do anything with it. You cannot call new over a referenced class object for example. That’s why Array(MyAbstractClass.class) is a non-sense, and you cannot either store Class object in variable in Crystal while it this can be useful in Java for example.
If you need to instantiate dynamically some objects using sort-of reflection, you must implement the factory pattern or use compile time linking with name matching to create and manage your link between the code and the Classes.
I would be happy to give you some help, as I faced this kind of design maze in Clear, as there’s some kind of reflection-ish things to deal with