I'm learning Clojure and I was wondering how to deal with OO-like subclasses in Clojure. For example: a master abstract class, two abstract subclasses (each one redefines some functions) and in the 3rd level, final subclasses that creates "objects" that will be used in the functions. No clue how to do this. However, I managed to do it with one abstract class to a child class, with defprotocol and defrecord. But I can't implement a protocol inside another. Thanks
You don't need classes or subclasses. Represent your data as maps with attributes. The "subclasses" might have more attributes.
If you have a function that varies on attribute, then either use conditional logic based on attribute (if, cond, etc) or use polymorphism based on multimethods or protocols if you really need to.
In the words of the Matrix, there is no spoon.
You can do inheritance with protocols like this:
(extend <subtype>
<protocol>
(merge (get-in <protocol> [:impls <basetype>])
<map-of-redefined-methods>))
Multimethods provide direct support for inheritance with derive.
Actual Java subclass relationships can be specified with the :extends keyword to gen-class. This is meant exclusively for Java interop, though.
Generally, it is worth checking whether you really need inheritance. It is usually not the preferred method of modeling in Clojure.
Related
I have the main abstract class that is a base for bunch of classes. Some of them does not need all the fields and methods from the main abstract class, so I have created second abstract class and splitted main abstract class into two parts. The main abstract class contains, for example, a, x fields and their getters/setters, the second abstract class inherits from the main and contains additional b, c fields and their getter/setters. There are simple classes that are inheriting from the main class,and more complicated are inheriting from the second class. I want to create objects of each class as instances of the main class. Is it right way to do that? I have to type check and cast when I want to use methods from the second abstract class. It makes my code complicated. How can I solve this problem?
MainAbstractClass ---> SecondAbstractClass ---> MyComplicatedClasses
|
|
V
MySimpleClasses
One of the OO principles is Favor composition over inheritance.
This means that common behavior is not provided through base classes but via Component classes which are passed in via dependency injection (preferably as constructor parameters.
The answer depends on your actual needs.
You can instead choose to store the extended abstract class specific fields in a class that does not implement your base class and make it a member of more complicated classes.
You can choose to keep everything in a single base class and nothing forces you to use all the fields of an interface in every class that implemented your interface.
You can also keep using your approach but since you store the classes as an instance of the base class, it will be hard to read.
I believe that if you think code does not look very good, it is probably not good. However, there is usually no single answer to this kind of design questions and the best solution is relative to your preferences.
I think this need of type cast is a smell of fragile design. Here when we assume MyComplicatedClass ISA KIND OF MainAbstractClass as shown by TJ Crowder then object must behave as MainAbstractClass (meaning it can honor only API of MainAbstractClass). If it expects special treatment as MyComplicatedClass its false commitment and will need Casting. Such casting (by identifying type) goes against OO principles and kills polymorphism. Later this will end up in Ladder of InstanceOf and type casts as in the scenarios rightly pointed out by T.J. Crowder.
I would suggest readdress the design. e.g. though our all user defined type instances ARE KIND OF Object, but we use Object API only for methods defined in Object class. We do not use Object o = new MyClass(). There are occasions in frameworks or like Object.equals() method where type cast is needed as API is defined before even concrete extension is written. But it is not a good idea for such simple complete (without open hooks for extensions) Hierarchies.
From the pdf of a java course: http://www.ccs.neu.edu/home/riccardo/courses/csu370-fa07/lect4.pdf
It says:
For those of you that follow at home, let me emphasize that subclassing is not inheritance. We will see inheritance later in the course.
Of course, subclassing and inheritance are related. As we will see inheritance is a code reuse mechanism that lets you reuse code easily when defining subclasses. But subclassing makes sense even when you do not have inheritance.
(Indeed, some languages have subclassing but no inheritance, at least, not inheritance like Java implements.)
Subclassing is a property of classes, and is properly part of the type system of Java. Subclassing is used by Java to determine what methods can possibly be invoked on an object, and to return an error at compile-time when an object does not supply a given method.
I want to know which languages have subclassing but no inheritance, at least, not inheritance like Java implements? (Since I'm not quite understand the concepts, so if I can see it in some actual languages, that would make it clearer)
This is a distinction without a difference. Clearly he is talking about inheritance of methods only when he uses the word "inheritance". He isn't using the term in the canonical way introduced by Wegner87, which is inextricably entwined with subclassing:
Inheritance: A class may inherit operations from “superclasses” and may have its operations inherited by “subclasses”. An object of the class C created by the operation “C new” has C as its “base class” and may use operations defined in its base class as well as operations defined in superclasses.
CS teachers often have strange notions. This has been one of them.
Say you have a set of objects that are arranged into a hierarchy. That is, there is an all encompassing object, then that object refers to several objects of the same kind but at a lower level, and each of those objects refer to several objects of the same kind but of a lower level, and so on for a variable number of steps. For example sake, lets consider these objects to be governments, so the highest level would be global, then global would have countries, and tribes, and countries would have towns, and towns would have houses, and businesses ect. All these governments extend the gov abstract class, so they all share the same kind.
I need to iterate through all the objects in the whole hierarchy, but because I don't know the complete structure at run-time, I have to do it in a generalized fashion.I only know for certain that there is a Global government, and then I have to check what sub-governments it has to proceed.
One way I'v found to do it is to give the super class a function called getSubGovs() which returns a list of all it's sub governments plus what each of those sub governments return from getSubGovs(). I hope that makes sense. It's a nice way to recurs through the problem.
What I'm looking for is a way to do this without having to add a function to the super class, for the case where I'm dealing with an API and cannot modify the super class. What would be an elegant way to do that?
This kind of structure is called a tree
Normally, every tree node has the same type, which has a getChildren() method or similar - in your case getSubGovs(). It sounds like each class has its own way of getting the children, so a straightforward abstraction is not possible.
The standard software pattern to apply that can navigate the tree in a generalised way is the visitor pattern, but because you can't modify the classes, you may need the facade pattern too.
I'm not 100% certain about what you want to achieve, but I believe what you would want here is polymorphism, namely inheritance and virtual functions (I dunno which language you are using but C++, for example, supports this).
Basically, you would make Global government the base class, and all your other classes the derived classes which would inherit Global government (or each other). Through inheritance you can establish the hierarchy you want (for example, by making classes lower in the hierarchy inherit from classes higher up in the hierarchy).
This page covers inheritance:
http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)
Now for the iterative part:
first, you declare functions/methods virtual (using the keyword virtual) in the base class (e.g. global government). The derived classes will overwrite this function and customize it however they want. Note that you do not need the virtual keyword in the derived classes.
Here is the cool part: while you are iterating through the mix of sub and super classes, you use the base class pointer for all. Even when you call the functions of derived classes from a base class pointer, because you declared the functions you need virtual, the C++ determines which version of the function to call based upon the type of the object pointed to by the pointer. This determination is made at runtime, therefore you don't even need to worry about which object in the hierarchy the pointer is pointing to.
This page covers virtual functions: http://en.wikipedia.org/wiki/Virtual_inheritance.
Hope this is the sort of thing you wanted.
EDIT:
According to this page:
How do you find all subclasses of a given class in Java?
There is no elegant method, you will have to look at every class on the classpath.
In Java to implement multiple inheritance we use interfaces. Is it the only use of interfaces? If yes, what is the main use of interface in Java? Why do we need interfaces in Java?
I would say the main use is polymorphism, or the ability to perform the same operation on a number of different objects. If different objects all implement the same interface and have the same method, you can store all of those objects in a Vector, for example, and iterate through the Vector calling that method on each one.
I was also thinking about how interfaces are used. I hope this will help others:
An interface is a contract (or a protocol, or a common understanding)
of what the classes can do. When a class implements a certain
interface, it promises to provide implementation to all the abstract
methods declared in the interface. Interface defines a set of common
behaviors. The classes implement the interface agree to these
behaviors and provide their own implementation to the behaviors. This
allows you to program at the interface, instead of the actual
implementation. One of the main usage of interface is provide a
communication contract between two objects. If you know a class
implements an interface, then you know that class contains concrete
implementations of the methods declared in that interface, and you are
guaranteed to be able to invoke these methods safely. In other words,
two objects can communicate based on the contract defined in the
interface, instead of their specific implementation.
Secondly, Java does not support multiple inheritance (whereas C++
does). Multiple inheritance permits you to derive a subclass from more
than one direct superclass. This poses a problem if two direct
superclasses have conflicting implementations. (Which one to follow in
the subclass?). However, multiple inheritance does have its place.
Java does this by permitting you to "implements" more than one
interfaces (but you can only "extends" from a single superclass).
Since interfaces contain only abstract methods without actual
implementation, no conflict can arise among the multiple interfaces.
(Interface can hold constants but is not recommended. If a subclass
implements two interfaces with conflicting constants, the compiler
will flag out a compilation error.)
from: http://www.ntu.edu.sg/home/ehchua/programming/java/J3b_OOPInheritancePolymorphism.html#zz-6.6
In addition to these responses I would say the most important use for interfaces is to reduce coupling between components in your software.
An interface allows to represent an agreement between classes on how they will talk to each other without being tied to the actual implementations.
This allows us to replace implementations by others (very useful for testing, or changing use cases) without changing the compiled code.
You need them so you can type your objects outside the hierarchy.
For example, the objects that can be compared can be pretty much anywhere on the object hierarchy - they do not need to have a common ancestor which can be compared. Strings can be compared, Integers can be compared, you could even make your own Frames that could be compared (say, a frame is "less" than another frame if it is more in the foreground - i.e. if it would overlay the other frame). Thus, if you want to refer to a thing that can be compared, you would be forced to declare a variable with the most general ancestor - in this case, Object. This is too general, because then it can also receive values which are not comparable (and would throw errors when you try to compare them).
Thus, the interface Comparable: it selects all the classes that implement the comparison functionality across the subclass-superclass hierarchy.
We need interfaces :
To achieve total abstraction.
To achieve security.
Java doesn't allow multiple inheritance but it can be achieved by implementing multiples interfaces.
Some code won't compile without it.
For example, in:
for (String name : list)
{
System.out.print("\nIn foreach loop: name: " + name);
}
list must implement the java.lang.Iterable interface.
In java, is there ever a case for allowing a non-abstract class to be extended?
It always seems to indicate bad code when there are class hierarchies. Do you agree, and why/ why not?
There are certainly times when it makes sense to have non-final concrete classes. However, I agree with Kent - I believe that classes should be final (sealed in C#) by default, and that Java methods should be final by default (as they are in C#).
As Kent says, inheritance requires careful design and documentation - it's very easy to think you can just override a single method, but not know the situations in which that method may be called from the base class as part of the rest of the implementation.
See "How do you design a class for inheritance" for more discussion on this.
I agree with Jon and Kent but, like Scott Myers (in Effective C++), I go much further. I believe that every class should be either abstract, or final. That is, only leaf classes in any hierarchy are really apt for direct instantiation. All other classes (i.e. inner nodes in the inheritance) are “unfinished” and should consequently be abstract.
It simply makes no sense for usual classes to be further extended. If an aspect of the class is worth extending and/or modifying, the cleaner way would be to take that one class and separate it into one abstract base class and one concrete interchangeable implementation.
there a good reasons to keep your code non-final. many frameworks such as hibernate, spring, guice depend sometimes on non-final classes that they extends dynamically at runtime.
for example, hibernate uses proxies for lazy association fetching.
especially when it comes to AOP, you will want your classes non-final, so that the interceptors can attach to it.
see also the question at SO
This question is equally applicable to other platforms such as C# .NET. There are those (myself included) that believe types should be final/sealed by default and need to be explicitly unsealed to allow inheritance.
Extension via inheritance is something that needs careful design and is not as simple as just leaving a type unsealed. Therefore, I think it should be an explicit decision to allow inheritance.
Your best reference here is Item 15 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". However the key to whether extension of a class should be allowed is not "is it abstract" but "was it designed with inheritance in mind". There is sometimes a correlation between the two, but it's the second that is important. To take a simple example most of the AWT classes are designed to be extended, even those that are not abstract.
The summary of Bloch's chapter is that interaction of inherited classes with their parents can be surprising and unpredicatable if the ancestor wasn't designed to be inherited from. Classes should therefore come in two kinds a) classes designed to be extended, and with enough documentation to describe how it should be done b) classes marked final. Classes in (a) will often be abstract, but not always. For
I disagree. If hierarchies were bad, there'd be no reason for object oriented languages to exist. If you look at UI widget libraries from Microsoft and Sun, you're certain to find inheritance. Is that all "bad code" by definition? No, of course not.
Inheritance can be abused, but so can any language feature. The trick is to learn how to do things appropriately.
In some cases you want to make sure there's no subclassing, in other cases you want to ensure subclassing (abstract). But there's always a large subset of classes where you as the original author don't care and shouldn't care. It's part of being open/closed. Deciding that something should be closed is also to be done for a reason.
I couldn't disagree more. Class hierarchies make sense for concrete classes when the concrete classes know the possible return types of methods that they have not marked final. For instance, a concrete class may have a subclass hook:
protected SomeType doSomething() {
return null;
}
This doSomething is guarenteed to be either null or a SomeType instance. Say that you have the ability to process the SomeType instance but don't have a use case for using the SomeType instance in the current class, but know that this functionality would be really good to have in subclasses and most everything is concrete. It makes no sense to make the current class an abstract class if it can be used directly with the default of doing nothing with its null value. If you made it an abstract class, then you would have its children in this type of hierarchy:
Abstract base class
Default class (the class that could have been non-abstract, only implements the protected method and nothing else)
Other subclasses.
You thus have an abstract base class that can't be used directly, when the default class may be the most common case. In the other hierarchy, there is one less class, so that the functionality can be used without making an essentially useless default class because abstraction just had to be forced onto the class.
Default class
Other subclasses.
Now, sure, hierarchies can be used and abused, and if things are not documented clearly or classes not well designed, subclasses can run into problems. But these same problems exist with abstract classes as well, you don't get rid of the problem just because you add "abstract" to your class. For instance, if the contract of the "doSomething()" method above required SomeType to have populated x, y and z fields when they were accessed via getters and setters, your subclass would blow up regardless if you used the concrete class that returned null as your base class or an abstract class.
The general rule of thumb for designing a class hierarchy is pretty much a simple questionaire:
Do I need the behavior of my proposed superclass in my subclass? (Y/N)
This is the first question you need to ask yourself. If you don't need the behavior, there's no argument for subclassing.
Do I need the state of my proposed superclass in my subclass? (Y/N)
This is the second question. If the state fits the model of what you need, this may be a canidate for subclassing.
If the subclass was created from the proposed superclass, would it truly be an IS-A relation, or is it just a shortcut to inherit behavior and state?
This is the final question. If it is just a shortcut and you cannot qualify your proposed subclass "as-a" superclass, then inheritance should be avoided. The state and logic can be copied and pasted into the new class with a different root, or delegation can be used.
Only if a class needs the behavior, state and can be considered that the subclass IS-A(n) instance of the superclass should it be considered to inherit from a superclass. Otherwise, other options exist that would be better suited to the purpose, although it may require a little more work up front, it is cleaner in the long run.
There are a few cases where we dont want to allow to change the behavior. For instance, String class, Math.
I don't like inheritance because there's always a better way to do the same thing but when you're making maintenance changes in a huge system sometimes the best way to fix the code with minimum changes is to extend a class a little. Yes, it's usually leads to a bad code but to a working one and without months of rewriting first. So giving a maintenance man as much flexibility as he can handle is a good way to go.