Confused about the definition of 'abstraction' in OOP - oop

I am trying to understand the definition of 'abstraction' in OOP.
I have come across two main definitions. Are they both valid? Is one of them wrong? I'm confused. (I re-wrote the definition with my own words).
Definition 1:
Abstraction is the concept of taking some object from the real world, and converting it to programming terms. Such as creating a Human class and giving it int health, int age, String name, etc. properties, and eat() etc. methods.
Definition 2:
A more general definition. Abstraction is a concept that takes place anywhere in a software system where 'making things more general/simpler/abstract' is involved. A few examples:
An inheritance hierarchy, where the higher classes are simpler or more general,
and define more general and abstract implementation.
While the lower classes in the hierarchy are more concrete and define
more detailed implementations.
Using encapsulation to hide the details of implementation of a class from other classes, thus making the class more 'abstract' (simpler) to the outside software world.
Is any of these definitions correct?
(I am referring to the most conventional and accepted definition).

Related

Is encapsulation just a capsula creation?

Recently I was talking to a very experienced programmer (8+ years of experience) and he told me that "combining data with functions that work with them in a capsula" is a wrong term for encapsulation. He told me that that was what encapsulation allowed me to do, but not what encapsulation itself was. He told me that as soon as inheritance is not possible without encapsulation, encapsulation must be just a capsula creation (class or anything like that). But today I got interviewed by a less experienced programmer and he was so sure all those classic definitions on wikipedia were right he told me not to even think of passing the interview. So I tried to google all that stuff about encapsulation, and about inheritence not being possible without encapsulation, but didn't find anything. But I can't believe that experienced programmer was wrong, he convienced not only me, but other experienced programmers too. Maybe that correct definition is just something that is lost in the chunks of useless and unimportant info?
So please, give me answers on these two questions:
1) can inheritence be possible without encapsulation? (A class's Inheritence from a class)
2) If not, then can we consider declaring a class encapsulation? Because only after declaring a class we can inherit.
Well, I'm Sorry, but I fail to see the connection between encapsulation and inheritance.
Encapsulation is hiding your internal implementation behind a publicly visible API.
Basically, it's a separation between a type's actual implementation and what it exposes.
In a broad sense, one can look at even the human body and see encapsulation:
For example: You are breathing air in and out, that's your public API, but the internals of what your body is doing with this air are hidden away inside your respiratory system - your lunges passes oxygen to your blood and collects from it carbon dioxide in return - thus changing the mixture ratio of the gasses in the air you breath, but none of this is visible to the outside world.
Inheritance, in the OOP world, is the ability to take a specific object, and derive an even more specific object from it, while adding capabilities (and sometimes mutating existing capabilities via overriding).
For example: A Dog is a kind of Mammal which is a kind of Animal.
An Animal might contain methods such as Eat() and properties such as Weight and Age.
A Mammal might override the Eat() method to implement suckling (from it's mother's breast) as an infant, but depending on it's age eating solid foods.
A Dog might introduce another capability such as Bark.
All of this have nothing to do with encapsulation as desribed in the previous paragraph.
Inheritance is tightly related to another core principle of object oriented programming called Polymorphism - basically, the ability to reference a derived class using it's base class type - perhaps you (or the interviewer) are confusing the two?
However, today is the first time I've seen another definition of encapsulation (and I've been working with oop languages for about two decades now):
A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.
Under that
definition, encapsulation is the process of creating capsules - stand-alone code snippets that holds data and ways to interact with it - a.k.a types, classes, etc', and is somewhat related to inheritance - in order to inherit a type, that type first needs to be defined.
However, the way I see it, this definition is not enough to define encapsulation. It can be a part of the definition, but not a stand-alone definition of encapsulation.

Inheritance over composition

The benefits of using composition over inheritance are quite well known;
What are the cases in which the opposite is preferable?
Practically, I can see the advantage of forcing a base constructor, but I would like to know other people's opinion about other cases/domains.
I believe the famous recommendation of "favor composition over inheritance" was coined in the GoF Design Patterns book.
It says (p.20):
Favor object composition over class inheritance.
Ideally, you shouldn't have to create new components to achieve reuse.
You should be able to get all the functionality you need just by
assembling existing components through object composition. But this is
rarely the case, because the set of available components is never
quite rich enough in practice. Reuse by inheritance makes it easier to
make new components that can be composed with old ones. Inheritance
and object composition thus work together.
Nevertheless, our experience is that designers overuse inheritance as
a reuse technique, and designs are often made more reusable (and
simpler) by depending more on object composition. You'll see object
composition applied again and again in the design patterns.
Notice that this statement refers to class inheritance, and must be distinguished from interface inheritance which is fine.
Dynamism
Both are ways to achieve reusability, but the advantage of composition over inheritance is dynamism. Since the composition can be changed dynamically at runtime this represents a great advantage, whereas inheritance is statically defined at compile time.
Encapsulation
Also, composition is based on using the public interfaces of the composed objects, therefore objects respect each other's public interfaces and therefore this fosters encapsulation. On the other hand, inheritance breaks encapsulation since child components typically consume a protected interface from the parent. It is a well known problem that changes in the parent class can break the child classes, the famous base class problem. Also in inheritance parent classes define the physical representation of subclasses, therefore child clases depend on parent classes to evolve.
Cohesion
Another advantage of composition is that it keeps classes focused on one task and this foster cohesion as well.
Liabilities
Evidently a problem with composition is that you will have more objects and fewer classes. That makes a little more difficult to visualize your design and how it achieves its goals. When debugging code it is harder to know what is going on unless you know what exact instance of a given composite is currently being used by an object. So composition makes designs a bit harder to understand in my opinion.
Since the advantages of composition are multiple that's why it is suggested to favor it over inheritance, but that does not mean inheritance is always bad. You can achieve a great deal when inheritance is properly used.
Interesting References
I would suggest a study of GoF Design Patterns to see good examples of both types of reusability, for instance a Strategy Pattern that uses composition vs a Template Method that uses inheritance.
Most of the patterns make a great use of interface inheritance and then object composition to achieve their goals and only a few use class inheritance as a reusability mechanism.
If you want to delve more the book Holub on Patterns, on chapter 2 has a section called Why extends is Evil that delve much more on the liabilities of class inheritance.
The book mentions three specific aspects
Losing Flexibility: The first problem is that explicit use of a concrete-class name locks you into a specific implementation, making
down-the-line changes unnecessarily difficult.
Coupling: A more important problem with implementation inheritance is coupling, the undesirable reliance of one part of a
program on another part. Global variables are the classic example of
why strong coupling is bad. If you change the type of a global
variable, for example, all the code that uses that variable—that is
coupled to the variable—can be affected, so all this code must be
examined, modified, and retested. Moreover, all the methods that use
the variable are coupled to each other through the variable. That is,
one method may incorrectly affect the behavior of another method
simply by changing the variable’s value at an awkward time. This
problem is particularly hideous in multithreaded programs.
Fragile-Base-Class Problem: In an implementation-inheritance system (one that uses extends), the derived classes are tightly
coupled to the base classes, and this close connection is undesirable.
Designers have applied the moniker “the fragile-base-class problem” to
describe this behavior. Base classes are considered “fragile” because
you can modify a base class in a seemingly safe way, but this new
behavior, when inherited by the derived classes, may cause the derived
classes to malfunction.
The only advantage of inheritance over composition that I can think of is that it can potentially save you from a lot of boiler plate method delegation.
If you truly have an is-a relationship and you simply want all the methods from a base class in your subclass, then inheritance gives you all those methods for free.
It's a complete debatable or argumentation question and broad as well.
AFAIK, when we talk about containership (or) something containing another thing we go for Composition; i.e, An entity contains another entity; which also gives a HAS A relationship. Example: EntityA has a EntityB.
See Decorator design pattern, which is based on the concept of Composition.
But when we talk about Inheritance we talk about IS A relationship. i.e, EntityA Is A EntityB (or) EntityA Is type of a EntityB
One special case when I find inheritance the best solution is when I use a runtime-generated class that need additional methods. For example (in C#):
public abstract class Rule{
/* properties here */
public Authorization Authorization { get; set; }
public abstract bool IsValid(dynamic request, User currentUser);
}
The generated template:
public class Generated_1Rule : Rule{
public override bool IsValid(dynamic request, User currentUser){
// the user script is here
}
}
Example of user script:
return Authorization.IsAuthorized("Module_ID_001", currentUser);
The benefit is that you can add functionality to the generated script “compiled-ly”, and it’s less breaking than inheriting from interface / composition since it is compiled.

What is the difference between subtyping and inheritance in OO programming?

I could not find the main difference. And I am very confused when we could use inheritance and when we can use subtyping. I found some definitions but they are not very clear.
What is the difference between subtyping and inheritance in object-oriented programming?
In addition to the answers already given, here's a link to an article I think is relevant.
Excerpts:
In the object-oriented framework, inheritance is usually presented as a feature that goes hand in hand with subtyping when one organizes abstract datatypes in a hierarchy of classes. However, the two are orthogonal ideas.
Subtyping refers to compatibility of interfaces. A type B is a subtype of A if every function that can be invoked on an object of type A can also be invoked on an object of type B.
Inheritance refers to reuse of implementations. A type B inherits from another type A if some functions for B are written in terms of functions of A.
However, subtyping and inheritance need not go hand in hand. Consider the data structure deque, a double-ended queue. A deque supports insertion and deletion at both ends, so it has four functions insert-front, delete-front, insert-rear and delete-rear. If we use just insert-rear and delete-front we get a normal queue. On the other hand, if we use just insert-front and delete-front, we get a stack. In other words, we can implement queues and stacks in terms of deques, so as datatypes, Stack and Queue inherit from Deque. On the other hand, neither Stack nor Queue are subtypes of Deque since they do not support all the functions provided by Deque. In fact, in this case, Deque is a subtype of both Stack and Queue!
I think that Java, C++, C# and their ilk have contributed to the confusion, as already noted, by the fact that they consolidate both ideas into a single class hierarchy. However, I think the example given above does justice to the ideas in a rather language-agnostic way. I'm sure others can give more examples.
A relative unfortunately died and left you his bookstore.
You can now read all the books there, sell them, you can look at his accounts, his customer list, etc. This is inheritance - you have everything the relative had. Inheritance is a form of code reuse.
You can also re-open the book store yourself, taking on all of the relative's roles and responsibilities, even though you add some changes of your own - this is subtyping - you are now a bookstore owner, just like your relative used to be.
Subtyping is a key component of OOP - you have an object of one type but which fulfills the interface of another type, so it can be used anywhere the other object could have been used.
In the languages you listed in your question - C++, Java and C# - the two are (almost) always used together, and thus the only way to inherit from something is to subtype it and vice versa. But other languages don't necessarily fuse the two concepts.
Inheritance is about gaining attributes (and/or functionality) of super types. For example:
class Base {
//interface with included definitions
}
class Derived inherits Base {
//Add some additional functionality.
//Reuse Base without having to explicitly forward
//the functions in Base
}
Here, a Derived cannot be used where a Base is expected, but is able to act similarly to a Base, while adding behaviour or changing some aspect of Bases behaviour. Typically, Base would be a small helper class that provides both an interface and an implementation for some commonly desired functionality.
Subtype-polymorphism is about implementing an interface, and so being able to substitute different implementations of that interface at run-time:
class Interface {
//some abstract interface, no definitions included
}
class Implementation implements Interface {
//provide all the operations
//required by the interface
}
Here, an Implementation can be used wherever an Interface is required, and different implementations can be substituted at run-time. The purpose is to allow code that uses Interface to be more widely useful.
Your confusion is justified. Java, C#, and C++ all conflate these two ideas into a single class hierarchy. However, the two concepts are not identical, and there do exist languages which separate the two.
If you inherit privately in C++, you get inheritance without subtyping. That is, given:
class Derived : Base // note the missing public before Base
You cannot write:
Base * p = new Derived(); // type error
Because Derived is not a subtype of Base. You merely inherited the implementation, not the type.
Subtyping doesn't have to be implemented via inheritance. Some subtyping that is not inheritance:
Ocaml's variant
Rust's lifetime anotation
Clean's uniqueness types
Go's interface
in a simple word: subtyping and inheritance both are polymorphism, (inheritance is a dynamic polymorphism - overriding). Actually, inheritance is subclassing, it means in inheritance there is no warranty to ensure capability of the subclass with the superclass (make sure subclass do not discard superclass behavior), but subtyping(such as implementing an interface and ... ), ensure the class does not discard the expected behavior.

How to move away from Inheritance

I've searched in here and other forums and couldn't find a good answer..
I kind of know that Extending classes isn't the best of practices. And that I should use Interfaces more. my problem is that usually I start creating Interfaces and then move to Abstract classes because there's always some functionality that I want implemented on a super class so that I don't have to replicate it in every child classes.
For instance, I have a Vehicle class and the Car and Bike child classes. a lot of functionality could be implemented on the Vehicle class, such as Move() and Stop(), so what would be the best practice to keep the architecture clean, avoid code repetition and use Interfaces instead of Inheritance?
Thanks a lot!
(if you have no idea why I'm asking this you may read this interesting article: http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html)
Inheritance ('extending classes') imposes significant limitations on class design and I'm not sure the use of interfaces as a replacement for inheritance is the best idea since it fails the DRY test.
These days, Composition is favored over Inheritance, so you might consider this post: Prefer composition over inheritance?
Interesting question. Everyone has different approaches. But it all based on personal experience and choice.
Usually, i start with an interface, then let an abstract class inherit that interface. And implement common actions there, and let others to be implemented by who ever inherits this class.
This give few advantageous based on by experience,
1.During function calls you can pass the elements as interface type or abstract class type.
2.Common variables such as ID, Names etc can be put on abstract class.
3.Easy for maintenance. For example, if you want to implement a new interface, then just implement in the abstract quickly.
If you keep in mind fundamental difference between interfaces and classes it will make it easier to decide which one to use. The difference is that interfaces represent just a protocol (usually behavioral) between objects involved, while abstract classes represent some unfinished constructions that involve some parts (data). In car example, interface is essentially a blueprint for the generic car. And abstract class would be like prefabricated specific model car body that needs to be filled with remaining parts to get final product. Interfaces don't even have to be in Java - it will not change anything - still blueprint.
Typically you would use abstract class within your specific implementation framework to provide its consumers with some basic functionality. If you just state that you never use abstract class in favor of interface - it's plain wrong from practical standpoint. What if you need 10 implementations of the same interface with 90% of the same code. Replicate code 10 times? Ok, may be you would use abstract class here but put interface on top of it. But why would you do that if you never intend to offer your class hierarchy to external consumers?
I am using word external in very wide sense - it can be just different package in your project or remote consumer.
Ultimately, many of those things are preferences and personal experiences, but I disagree with most blanket statements like extends is evil. I also prefer not to use extra classes (interfaces or abstract) unless it is required by specific parts of the design.
Just my two cents.
Inheritance allows code reuse and substitutability, but restricts polymorphism. Composition allows code reuse but not substitutability. Interfaces allow substitutability but not code reuse.
The decision of whether to use inheritance, composition, or interfaces, boils down to a few simple principles:
If one needs both code reuse and substitutability, and the restrictions imposed on polymorphism aren't too bad, use inheritance.
If one needs code reuse, but not substitutability, use composition.
If one needs substitutability, but not code reuse, or if the restrictions inheritance would impose upon polymorphism would be worse than duplicated code, use interfaces.
If one needs substitutability and code reuse, but the restrictions imposed by polymorphism would be unacceptable, use interfaces to wrap encapsulated objects.
If one needs substitutability and code reuse, and the restrictions imposed by polymorphism would not pose any immediate problem but might be problematic for future substitutable classes, derive a model base class which implements an interface, and have those classes that can derive from it do so. Avoid using variables and parameters of the class type, though--use the interface instead. If you do that, and there is a need for a substitutable class which cannot very well derive from the model base class, the new class can implement the interface without having to inherit from the base; if desired, it may implement the interface by wrapping an encapsulated instance of a derivative of the model type.
Judgment may be required in deciding whether future substitutable classes may have difficulty deriving from a base class. I tend to think approach #5 often offers the best of all worlds, though, when substitutability is required. It's often cheaper than using interfaces alone, and not much more expensive than using inheritance alone. If there is a need for future classes which are substitutable but cannot be derived from the base, it may be necessary to convert the code to use approach #5. Using approach #5 from the get-go would avoid having to refactor the code later. (Of course, if it's never necessary to substitute a class that can't derive from the base, the extra cost--slight as it may be--may end up being unnecessary).
Agree with tofutim - in your current example, move and stop on Vehicle is reasonable.
Having read the article - I think it's using powerful language to push a point... remember - inheritance is a tool to help get a job done.
But if we go with the assumption that for whatever reasons you can't / won't use the tool in this case, you can start by breaking it down into small interfaces with helper objects and/or visitors...
For example -
Vehicle types include submarine, boat, plane, car and bike. You could break it down into interfaces...
IMoveable
+ Forward()
+ Backward()
+ Left()
+ Right()
IFloatable
+ Dock()
ISink()
+ BlowAir()
IFly()
+ Takeoff()
+ Land()
And then your classes can aggregate the plethora of interfaces you've just defined.
The problem is though that you may end up duplicating some code in the car / bike class for IMoveable.Left() and IMoveable.Right(). You could factor this into a helper method and aggregate the helper... but if you follow it to its logical conclusion, you would still end up refactoring many things back into base classes.
Inheritance and Aggregation are tools... neither of which are "evil".
Hope that helps.
Do you want an answer for your specific case, or in general? In the case you described, there is nothing wrong with using an Abstract class. It doesn't make sense use an interface when all of the clients would need to implement the exact same code for Move() and Stop().
Don't believe all you read
Many times, inheritance is not bad, in fact, for data-hiding, it may be a good idea.
Basically, only use the policy of "interfaces only" when you're making a very small tree of classes, otherwise, I promise it will be a pain. Suppose you have a Person "class" (has eat() and sleep), and there are two subclasses, Mathematician (has doProblem() ) and Engineer ( buildSomething() ), then go with interfaces. If you need something like a Car class and then 56 bazillion types of cars, then go with inheritance.
IMHO.
I think, that Interfaces sometime also evil. They could be as avoidance of multiple inheritance.
But if we compare interface with abstract class, then abstract class is always more than interface. Interface is always some aspect of the class -- some viewpoint, and not whole as a class.
So I don't think you should avoid inheritance and use iterfaces everywhere -- there should be balance.

Should I be using inheritance?

This is more of a subjective question, so I'm going to preemptively mark it as community wiki.
Basically, I've found that in most of my code, there are many classes, many of which use each other, but few of which are directly related to each other. I look back at my college days, and think of the traditional class Cat : Animal type examples, where you have huge inheritance trees, but I see none of this in my code. My class diagrams look like giant spiderwebs, not like nice pretty trees.
I feel I've done a good job of separating information logically, and recently I've done a good job of isolating dependencies between classes via DI/IoC techniques, but I'm worried I might be missing something. I do tend to clump behavior in interfaces, but I simply don't subclass.
I can easily understand subclassing in terms of the traditional examples such as class Dog : Animal or class Employee : Person, but I simply don't have anything that obvious I'm dealing with. And things are rarely as clear-cut as class Label : Control. But when it comes to actually modeling real entities in my code as a hierarchy, I have no clue where to begin.
So, I guess my questions boil down to this:
Is it ok to simply not subclass or inherit? Should I be concerned at all?
What are some strategies you have to determine objects that could benefit from inheritance?
Is it acceptable to always inherit based on behavior (interfaces) rather than the actual type?
Inheritance should always represent an "is-a" relationship. You should be able to say "A is a B" if A derives from B. If not, prefer composition. It's perfectly fine to not subclass when it is not necessary.
For example, saying that FileOpenDialog "is-a" Window makes sense, but saying that an Engine "is-a" Car is nonsense. In that case, an instance of Engine inside a Car instance is more appropriate (It can be said that Car "is-implemented-in-terms-of" Engine).
For a good discussion of inheritance, see Part 1 and Part 2 of "Uses and Abuses of Inheritance" on gotw.ca.
As long as you do not miss the clear cut 'is a' relationships, it's ok and in fact, it's best not to inherit, but to use composition.
is-a is the litmus test. if (Is X a Y?) then class X : Y { } else class X { Y myY; } or class Y { X myX; }
Using interfaces, that is, inheriting behavior, is a very neat way to structure the code via adding only the needed behavior and no other. The tricky part is defining those interfaces well.
No technology or pattern should be used for its own sake. You obviously work in a domain where classes tend to not benefit from inheritance, so you shouldn't use inheritance.
You've used DI to keep things neat and clean. You separated the concerns of your classes. Those are all good things. Don't try and force inheritance if you don't really need it.
An interesting follow-up to this question would be: Which programming domains do tend to make good use of inheritance? (UI and db frameworks have already been mentioned and are great examples. Any others?)
I also hate the Dog -> Mammal -> Animal examples, precisely because they do not occur in real life.
I use very little subclassing, because it tightly couples the subclass to the superclass and makes your code really hard to read. Sometimes implementation inheritance is useful (e.g. PostgreSQLDatabaseImpl and MySQLDatabaseImpl extend AbstractSQLDatabase), but most of the time it just makes a mess of things. Most of the time I see subclasses the concept has been misused and either interfaces or a property should be used.
Interfaces, however, are great and you should use those.
Generally, favour composition over inheritance. Inheritance tends to break encapsulation. e.g. If a class depends on a method of a super class and the super class changes the implementation of that method in some release, the subclass may break.
At times when you are designing a framework, you will have to design classes to be inherited. If you want to use inheritance, you will have to document and design for it carefully. e.g. Not calling any instance methods (that could be overridden by your subclasses) in the constructor. Also if its a genuine 'is-a' relationship, inheritance is useful but is more robust if used within a package.
See Effective Java (Item 14, and 15). It gives a great argument for why you should favour composition over inheritance. It talks about inheritance and encapsulation in general (with java examples). So its a good resource even if you are not using java.
So to answer your 3 questions:
Is it ok to simply not subclass or inherit? Should I be concerned at all?
Ans: Ask yourself the question is it a truly "is-a" relationship? Is decoration possible? Go for decoration
// A collection decorator that is-a collection with
public class MyCustomCollection implements java.util.Collection {
private Collection delegate;
// decorate methods with custom code
}
What are some strategies you have to determine objects that could benefit from inheritance?
Ans: Usually when you are writing a framework, you may want to provide certain interfaces and "base" classes specifically designed for inheritance.
Is it acceptable to always inherit based on behavior (interfaces) rather than the actual type?
Ans: Mostly yes, but you'd be better off if the super class is designed for inheritance and/or under your control. Or else go for composition.
IMHO, you should never do #3, unless you're building an abstract base class specifically for that purpose, and its name makes it clear what its purpose is:
class DataProviderBase {...}
class SqlDataProvider : DataProviderBase {...}
class DB2DataProvider : DataProviderBase {...}
class AccountDataProvider : SqlDataProvider {...}
class OrderDataProvider : SqlDataProvider {...}
class ShippingDataProvider : DB2DataProvider {...}
etc.
Also following this type of model, sometimes if you provide an interface (IDataProvider) it's good to also provide a base class (DataProviderBase) that future consumers can use to conveniently access logic that's common to all/most DataProviders in your application model.
As a general rule, though, I only use inheritance if I have a true "is-a" relationship, or if it will improve the overall design for me to create an "is-a" relationship (provider model, for instance.)
Where you have shared functionality, programming to the interface is more important than inheritance.
Essentially, inheritance is more about relating objects together.
Most of the time we are concerned with what an object can DO, as opposed to what it is.
class Product
class Article
class NewsItem
Are the NewsItem and Article both Content items? Perhaps, and you may find it useful to be able to have a list of content which contains both Article items and NewsItem items.
However, it's probably more likely you'll have them implement similar interfaces. For example, IRssFeedable could be an interface that they both implement. In fact, Product could also implement this interface.
Then they can all be thrown to an RSS Feed easily to provide lists of things on your web page. This is a great example when the interface is important whereas the inheritance model is perhaps less useful.
Inheritance is all about identifying the nature of Objects
Interfaces are all about identifying what Objects can DO.
My class hierarchies tend to be fairly flat as well, with interfaces and composition providing the necessary coupling. Inheritance seems to pop up mostly when I'm storing collections of things, where the different kinds of things will have data/properties in common. Inheritance often feels more natural to me when there is common data, whereas interfaces are a very natural way to express common behavior.
The answer to each of your 3 questions is "it depends". Ultimately it will all depend on your domain and what your program does with it. A lot of times, I find the design patterns I choose to use actually help with finding points where inheritance works well.
For example, consider a 'transformer' used to massage data into a desired form. If you get 3 data sources as CSV files, and want to put them into three different object models (and maybe persist them into a database), you could create a 'csv transformer' base and then override some methods when you inherit from it in order to handle the different specific objects.
'Casting' the development process into the pattern language will help you find objects/methods that behave similarly and help in reducing redundant code (maybe through inheritance, maybe through the use of shared libraries - whichever suits the situation best).
Also, if you keep your layers separate (business, data, presentation, etc.), your class diagram will be simpler, and you could then 'visualize' those objects that aught to be inherited.
I wouldn't get too worried about how your class diagram looks, things are rarely like the classroom...
Rather ask yourself two questions:
Does your code work?
Is it extremely time consuming to maintain? Does a change sometimes require changing the 'same' code in many places?
If the answer to (2) is yes, you might want to look at how you have structured your code to see if there is a more sensible fashion, but always bearing in mind that at the end of the day, you need to be able to answer yes to question (1)... Pretty code that doesn't work is of no use to anybody, and hard to explain to the management.
IMHO, the primary reason to use inheritance is to allow code which was written to operate upon a base-class object to operate upon a derived-class object instead.