Can you provide scenarios when we inherit from a class, it works for a while, but then something else changes and introduces a bug? I came up with the following situation:
- to implement Rectangle-with-hole, we inherit from class Rectangle. In the constructor, we check that the hole is inside the rectangle
- Later someone adds a new method Resize to class Rectangle. They 开发者_如何学Pythondon't check if the hole is still inside.
- After Resize, we can have Rectangle-with-holes with holes not inside rectangles, which is a bug.
What are the other problems I should be careful if I choose to use object inheritance in C#.
What you are describing is one of the pitfalls of inheritance.
Another pitfall is a deep inheritance hierarchy. Stackoverflow thread on composition over inheritance.
There are many ways a change to a base class can affect derived class behaviour. What if the author suddenly decided to make the class sealed
for example?
Like any interface it needs to be stable if consumers are to not require modification.
The primary "rule" with inheritance is the Liskov Substition Principle. This states that the derived class should be substitutable for the base class or other classes derived from it.
This case breaks this rule on the face of it, as a rectangle with a hole is not a rectangle.
Usually it's best to use interfaces to divide behaviour into sensible implementable chunks. Such interfaces are generally named with adjectives rather than nouns. For example, it makes sense for both a rectangle and a rectangle with a hole to be rendered, so an interface might be IRenderable
. If it's resizable you might have a IResizable
, etc. These could be aggregated into an IShape
, but you want to be careful that your definition of Shape defines just the behaviours in your problem domain.
Directly deriving from another class can be dangerous as you're then bound by the behaviour of that class. If you genuinely need to do that it can be best to extract the implementation you need into a common base class (e.g. Rectangle : RectangleImplementation, IShape
).
This is known as the brittle base class problem.
Another potential problem with inheritance in general is when you would like to use your own base class but a framework requires a specific base class (e.g., ContextBoundObject
) instead of an interface.
That's why the prescient C# language designers added the sealed keyword to the language. Use judiciously.
And use code contracts to test your invariants to get an early warning about breakage.
Don't call a virtual method in a constructor. See Eric Lippert's posts about it (part 1 and part 2).
I think this is not related with c# or inheritance. No matter you do, this is inevitable problem of software development.
Best and simply solution is build your code daily and perform unit testing.
Better use -Decorator Pattern in these types of cases. This provides better way of extension.
This can be implemented using the following diagram:
The rectangle object will be created and wrapped into a HoleDecorator object which will be responsible for providing the hole. When resizing of the Rectangle is done, the Resizing of HoleDecorator will be called, this will call the Resize of the Rectangle object first and then calls the AddedBehavior for the Hole Decorator which will specify what to be done to the hole when the main component is resized.
精彩评论