Abstract methods and NotImplementedError in Ruby
๐ Abstract
The article discusses the use of the NotImplementedError
exception in Ruby, and how it is commonly misused as a placeholder in abstract classes for methods that should be implemented by subclasses. It explains the actual purpose of NotImplementedError
and provides alternative approaches to handling abstract methods in Ruby.
๐ Q&A
[01] Common Usage Pattern of NotImplementedError
1. What is a common usage pattern of NotImplementedError
in Ruby?
A common usage pattern of NotImplementedError
is to raise it in a base class to indicate that a method should be implemented by subclasses. For example:
class BaseSetting
def to_html
raise NotImplementedError
end
end
class Text < BaseSetting
def to_html
"<input type='text'>"
end
end
class Number < BaseSetting
# Forgot to implement to_html
end
In this case, the Text
class implements the to_html
method, but the Number
class does not, so raising NotImplementedError
will result in an exception when NumberSetting.new.to_html
is called.
2. What is the actual intended use of NotImplementedError
in Ruby?
The article states that NotImplementedError
is actually intended to be raised when a feature is not implemented on the current platform, such as when calling Process.fork
on a platform that does not support it.
3. What are the issues with using NotImplementedError
for abstract methods?
The article mentions a few issues with using NotImplementedError
for abstract methods:
- It is not the intended use of the exception
- It can be difficult to rescue, as it inherits from
ScriptError
instead ofStandardError
- It can lead to unexpected behavior when used with exception handling, such as in the
convert_to_html
example
[02] Alternative Approaches to Handling Abstract Methods
1. What are some alternative approaches to handling abstract methods in Ruby? The article presents several alternative approaches to handling abstract methods, including:
- Providing a default implementation in the base class
- Explicitly raising an exception with a clear error message
- Creating a custom exception that inherits from
StandardError
- Raising
NoMethodError
instead - Writing tests to ensure subclasses implement the required methods
- Using a static type checker like Sorbet to enforce abstract method implementation
2. What are the benefits of these alternative approaches? The alternative approaches aim to:
- Provide a more explicit and intentional way to handle abstract methods
- Ensure that the exception handling behavior is more predictable
- Avoid the misuse of
NotImplementedError
- Improve the overall maintainability and robustness of the codebase
3. What is the recommendation for using NotImplementedError
in Ruby?
The article suggests that if using NotImplementedError
is working well for your codebase, there's no need to go back and replace everything. However, if you want to change the approach, the article provides several alternative options to consider.