189

Basically we want things to behave sensibly. Consider the following problem: I am given a group of rectangles and I want to increase their area by 10%. So what I do is I set the length of the rectangle to 1.1 times what it was before. public void IncreaseRectangleSizeByTenPercent(IEnumerable<Rectangle> rectangles) { foreach(var rectangle in ...


127

A common misunderstanding with the DRY principle is that it is somehow related to not repeating lines of code. The DRY principle is "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system". It's about knowledge, not code. LoginPage knows about how to draw the page for logging in. If EditInfoPage knew how to ...


127

I wouldn't use any form of inheritance for World and Country. The World is not a Country, and a Country is not the World. Instead, the World is a "bag" which contains many Countries. By "bag" I mean some kind of container class of your choosing (linked list, set, dictionary/map, or whatever). Pick whichever container type allows you to most efficiently ...


119

Gosh, there are some weird misconceptions on what OCP and LSP and some are due to mismatch of some terminologies and confusing examples. Both principles are only the "same thing" if you implement them the same way. Patterns usually follow the principles in one way or another with few exceptions. The differences will be explained further down but first let ...


83

From my perspective: your design is wrong. Translated to natural language, you are saying the following: Given we have animals, there are cats and fish. animals have properties, which are common to cats and fish. But that's not enough: there are some properties, which differentiate cat from fish, therefore you need to subclass. Now you have the problem, ...


82

Preferring composition isn't just about polymorphism. Although that is part of it, and you are right that (at least in nominally typed languages) what people really mean is "prefer a combination of composition and interface implementation." But, the reasons to prefer composition (in many circumstances) are profound. Polymorphism is about one thing ...


78

UPDATE: I've revised this answer. A number of good points were raised in the comments that deserved calling out. If my class implements an interface then can I say that I'm following inheritance? It is not entirely clear what you mean by "following inheritance". Let's ask a slightly different question? What is inheritance? When members of one type X ...


77

There is no need to have specific subclasses for every person. You're right, those should be instances instead. Goal of subclasses: to extend parent classes Subclasses are used to extend the functionality provided by the parent class. For example, you may have: A parent class Battery which can Power() something and can have a Voltage property, And a ...


71

The simplest answer is that if you put everything into one class, you have to worry about everything at once when you're writing new code. This may work for small projects, but for huge applications (we're talking hundreds of thousands of lines), this quickly becomes next to impossible. To solve this issue, you break up pieces of functionality into their ...


70

In many cases, people use inheritance to provide a trait to a class. For example think of a Pegasus. With multiple inheritance you might be tempted to say the Pegasus extends Horse and Bird because you've classified the Bird as an animal with wings. However, Birds have other traits that Pegasi don't. For example, birds lay eggs, Pegasi have live birth. If ...


69

It depends on the context, but I would argue you should declare the most abstract type possible. That way your code will be as general as possible and not depend on irrelevant details. An example would be having a LinkedList and ArrayList which both descend from List. If the code would work equally well with any kind of list then there is no reason to ...


63

A commitment is something that reduces your future options. Publishing a method implies that users will call it, therefore you can't remove this method without breaking compatibility. If you'd kept it private, they couldn't (directly) call it, and you could some day refactor it away without problems. Therefore, publishing a method is a stronger commitment ...


63

This is something that I use to prevent polymorphism from being used. Say you have 15 different classes that have NamedEntity as a base class somewhere in their inheritance chain and you are writing a new method that is only applicable to OrderDateInfo. You "could" just write the signature as void MyMethodThatShouldOnlyTakeOrderDateInfos(NamedEntity ...


60

Is there something that I am not seeing here? Allowing multiple inheritence makes the rules about function overloads and virtual dispatch decidedly more tricky, as well as the language implementation around object layouts. These impact language designers/implementors quite a bit, and raise the already high bar to get a language done, stable and adopted. ...


58

The general rule reads "Prefer delegation over inheritance", not "avoid all inheritance". If the objects have a logical relationship and a B can be used wherever an A is expected, it is good practice to use inheritance. However, if the objects just happen to have fields with the same name, and have no domain relationship, do not use inheritance. Quite ...


54

If all you want to do is create class X with certain arguments, subclassing is an odd way of expressing that intent, because you aren't using any of the features that classes and inheritance give you. It's not really an anti-pattern, it's just strange and a bit pointless (unless you have some other reasons for it). A more natural way of expressing this ...


51

Polymorphism does not necessarily imply inheritance. Often inheritance is used as an easy means to implement Polymorphic behaviour, because it is convenient to classify similar behaving objects as having entirely common root structure and behaviour. Think of all those car and dog code examples you've seen over the years. But what about objects that aren't ...


50

It's completely terrible in every possible way. At most, use a factory function to produce JButtons. You should only inherit from them if you have some serious extension needs.


46

Er wait you're concerned that repeating public LoginPage loginPage; in two places violates DRY? By that logic int x; can now only ever exist in one object in the entire code base. Bleh. DRY is a good thing to keep in mind but come on. Besides ... extends LoginPage is getting duplicated in your alternative so even being anal about DRY wont make sense ...


41

There can't be any proper inheritance of constructors in C++, because the constructor of a derived class needs to perform additional actions that a base-class constructor does not have to do and does not know about. These additional actions are the initialisation of the data members of the derived class (and in a typical implementation, also setting the ...


35

In principle there's no difference between inheriting from generic types and inheriting from anything else. However, why on earth would you derive from any class and not add anything further?


35

You want to avoid base classes knowing about derived classes. It introduces tight coupling and is a maintenance headache because you have to remember to add to the list every time you create a new derived class. It will also prevent you from being able to put the Notification class into a reusable package/assembly if you wanted to use this class in ...


34

It all depends upon the exact problem you're trying to solve. Consider a concrete example: your abstract base class is Vehicle and you currently have the concrete implementations Bicycle and Car. You're considering moving numberOfWheels from Bicycle and Car to vehicle. Should you do this? No! Because not all vehicles have wheels. You can already tell that ...


33

You ask why, as if the whether is decided. Lets consider your supposition: Why is inheritance generally viewed as a bad thing by OOP proponents I disagree with the premise of the question. Inheritance isn't generally viewed as bad, it is viewed as misused and overused. GoF Design Patterns says no such thing about it being bad. Let's see what GoF ...


32

There are a number of problems with multiple inheritance when it is used with full fledged classes, but they all revolve around ambiguity. The ambiguity shows up in a few different ways: If you have two base classes with the same field x, and the derived type asks for x, what does it get? If the two x variables have incongruent types, you could infer it. ...


31

This seems to be too big a difference to just boil down to style. What is the reasoning behind this? My understanding is that it largely is simply a stylistic decision. Well, perhaps not style, but the idioms of the language/environment. Java standard library developers followed one set of design guidelines and the .NET developers another (though they had ...


31

The seminal paper on mixins is Gilad Bracha's PhD thesis The Programming Language Jigsaw: Mixins, Modularity and Multiple Inheritance. It has answers to all of your questions, like Why not make a language with mixin-only inheritance? Jigsaw is such a language, as is Newspeak, Bracha's current language However, to me it looks like traditional ...


30

If all your objects are immutable, there is no problem. Every Square is also a Rectangle. All the properties of a Rectangle are also properties of a Square. The problem begins when you add the ability to modify the objects. Or really - when you start passing arguments to the object, not just reading property getters. There are modifications that you can do ...


30

If you publish a normal function, you give a one-sided contract: What does the function do if called? If you publish a callback, you also give a one-sided contract: When and how will it be called? And if you publish an overridable function, it's both at once, so you give a two-sided contract: When will it be called, and what must it do if called? Even if ...


30

That all seems like a fine description of what type systems provide. And your implementation sounds like a reasonable enough one for what it's doing. For some languages, you won't need the runtime information since your language doesn't do runtime dispatch (or you do single dispatch via vtables or another mechanism, so don't need the type information). For ...


Only top voted, non community-wiki answers of a minimum length are eligible