final
может быть полезна, когда вы предоставляете (вид) фасад первоначальному интерфейсу, который проще использовать подклассами. Рассмотрим:
class IMovable {
public:
void GoTo(unsigned position) = 0;
}
class Stepper : public IMovable {
public:
void GoTo(unsigned position) final;
protected:
virtual void MoveLeft() = 0;
virtual void MoveRight() = 0;
}
void Stepper::GoTo(unsigned position) {
for(;current_pos < position; current_pos++) {
MoveRight();
}
for(;current_pos > position; current_pos--) {
MoveLeft();
}
}
Теперь, если вы хотите получить Stepper, вы увидите, что вы должны переопределить MoveRight
и MoveLeft
, но вы не должны переопределять GoTo
.
Это очевидно на этом маленьком примере, но если IMovable
имеет 20 методов, а у Stepper 25, и были реализации по умолчанию, чем вам может быть трудно выяснить, что вы должны и что вы должны " t переопределить. Я встречал такую ситуацию в библиотеке, связанной с оборудованием. Но я бы не назвал это серьезной проблемой, заслуживающей внимания стандартом;)
Вы можете использовать instance_variable_set
, вам не нужно полагаться на attr writer:
def initialize(data)
data.each { |key, value| instance_variable_set("@#{key}", value) }
end