История изменений
Исправление Manhunt, (текущая версия) :
Программные сущности должны быть открыты для расширения, но закрыты для изменения.
Так как наследование отсутствует, выбора, собственно говоря, нет: мы не можем менять сущности.
Отсутствует наследование реализаций, точнее сахар для оного. Оно и не нужно. Под «сущностью» в формулировке open-closed следует понимать абстракции (т.е. интерфейсы, трейты, контракты), от которых (в правильно спроектированной программе) должен зависеть наш код. Эти самые трейты и нельзя менять (а можно только расширять), иначе значительные объемы кода окажутся разломаны. Что касается реализаций трейтов, то нет ничего дурного в том, что они меняются: остальная программа должна этого попросту не замечать. «Using the principles of object oriented design, it is possible to create abstractions that are fixed and yet represent an unbounded group of possible behaviors. The abstractions are abstract base classes, and the unbounded group of possible behaviors is represented by all the possible derivative classes. It is possible for a module to manipulate an abstraction. Such a module can be closed for modification since it depends upon an abstraction that is fixed. Yet the behavior of that module can be extended by creating new derivatives of the abstraction». http://www.objectmentor.com/resources/articles/ocp.pdf
Sometimes, implementing a trait requires implementing another trait:
trait Foo {
fn foo(&self);
}
trait FooBar : Foo {
fn foobar(&self);
}
Implementors of FooBar must also implement Foo, like this:
struct Baz;
impl Foo for Baz {
fn foo(&self) { println!("foo"); }
}
impl FooBar for Baz {
fn foobar(&self) { println!("foobar"); }
}
⇱
If we forget to implement Foo, Rust will tell us:
error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277]
Исходная версия Manhunt, :
Программные сущности должны быть открыты для расширения, но закрыты для изменения.
Так как наследование отсутствует, выбора, собственно говоря, нет: мы не можем менять сущности.
Отсутствует наследование реализаций, точнее сахар для оного. Оно и не нужно. Под «сущностью» в формулировке open-closed следует понимать абстракции (т.е. интерфейсы, трейты, контракты), от которых (в правильно спроектированный программе) должен зависеть наш код. Эти самые трейты и нельзя менять (а можно только расширять), иначе значительные объемы кода окажутся разломаны. Что касается реализаций трейтов, то нет ничего дурного в том, что они меняются: остальная программа должна этого попросту не замечать. «Using the principles of object oriented design, it is possible to create abstractions that are fixed and yet represent an unbounded group of possible behaviors. The abstractions are abstract base classes, and the unbounded group of possible behaviors is represented by all the possible derivative classes. It is possible for a module to manipulate an abstraction. Such a module can be closed for modification since it depends upon an abstraction that is fixed. Yet the behavior of that module can be extended by creating new derivatives of the abstraction». http://www.objectmentor.com/resources/articles/ocp.pdf
Sometimes, implementing a trait requires implementing another trait:
trait Foo {
fn foo(&self);
}
trait FooBar : Foo {
fn foobar(&self);
}
Implementors of FooBar must also implement Foo, like this:
struct Baz;
impl Foo for Baz {
fn foo(&self) { println!("foo"); }
}
impl FooBar for Baz {
fn foobar(&self) { println!("foobar"); }
}
⇱
If we forget to implement Foo, Rust will tell us:
error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277]