module Dry::Core::ClassAttributes

def defines(*args, type: ::Object, coerce: IDENTITY) # rubocop:disable Metrics/PerceivedComplexity

Other tags:
    Example: with coercion using dry-types -
    Example: with coercion using Proc -
    Example: with dry-types -
    Example: with inheritance and type checking -
def defines(*args, type: ::Object, coerce: IDENTITY) # rubocop:disable Metrics/PerceivedComplexity
  unless coerce.respond_to?(:call)
    raise ::ArgumentError, "Non-callable coerce option: #{coerce.inspect}"
  end
  mod = ::Module.new do
    args.each do |name|
      ivar = :"@#{name}"
      define_method(name) do |value = Undefined|
        if Undefined.equal?(value)
          if instance_variable_defined?(ivar)
            instance_variable_get(ivar)
          else
            nil
          end
        elsif type === value # rubocop:disable Style/CaseEquality
          instance_variable_set(ivar, coerce.call(value))
        else
          raise InvalidClassAttributeValueError.new(name, value)
        end
      end
    end
    define_method(:inherited) do |klass|
      args.each { |name| klass.send(name, send(name)) }
      super(klass)
    end
  end
  extend(mod)
end