Ничего плохого в вашем подходе. Вызывать ошибку при инициализации кажется нормальным, если конечно все ваши подклассы переопределяют инициализацию. Но вы не хотите определять self.new таким образом. Вот что я бы сделал.
class A
class AbstractClassInstiationError < RuntimeError; end
def initialize
raise AbstractClassInstiationError, "Cannot instantiate this class directly, etc..."
end
end
Другой подход - поместить всю эту функциональность в модуль, который, как вы упомянули, никогда не может быть реализован. Затем включите модуль в свои классы, а не наследуйте от другого класса. Однако это сломало бы такие вещи, как супер.
Так что это зависит от того, как вы хотите его структурировать. Хотя модули кажутся более чистым решением для решения проблемы «Как написать некоторые вещи, которые предназначены для использования другими классами»