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.
Related
Java 17 has introduced sealed classes which can permit only specific classes to extend them and would otherwise be final
I understand the technical use-case, but can't think of any real life use cases where this would be useful?
When would we want only specific classes to be able to extend a particular class?
In our own projects, if we want a new class to extend the sealed class can't we just add it to the permitted classes? Wouldn't it be better to just not make the class final or sealed in that case to avoid the slight overhead?
On the other hand, while exposing a library for external use how would a sealed class know beforehand which classes it should permit for extension?
sealed classes provide the opposite guarantee to open classes (the default in Java). An open class says to implementors "Hey, you can subclass me and override my non-final methods", but it says to users "I have no idea what subclasses look like, so you can only use my own methods directly". On the flipside, sealed classes are very restrictive to implementors "You cannot subclass me, and you can only use me in these prescribed ways", but very powerful to users: "I know in advance all of my subclasses, so you know that if you have an instance of me, then it must be one of X, Y, or Z". Consequently, adding a subclass to a sealed class is a breaking change.
It may be helpful to think of sealed classes less as "restricted classes" and more as "enums with superpowers". An enum in Java is a finite set of data values, all constructed in advance. A sealed class is a finite set of classes that you set forth, but those classes may have an infinite number of possible instances.
Here's a real-world example that I wrote myself recently. This was in Kotlin, which also has sealed classes, but it's the same idea. I was writing a wrapper for some Minecraft code and I needed a class that could uniformly represent all of the ways you can die in Minecraft. Long story short, I ended up partitioning the death reasons into "killed by another living thing" and "all other death reasons". So I wrote a sealed interface CauseOfDeath. Its two implementors were VanillaDeath (which took a "cause of damage" as its constructor argument, basically an enum listing all of the possible causes) and VanillaMobDeath (which took the specific entity that killed you as its constructor argument).
Since this was clearly exhaustive, I made it sealed. If Minecraft later adds more death reasons, they will fit into one of the two categories ("death by entity" or "death by other causes"), so it makes no sense for me or anyone else to ever subclass this interface again.
Further, since I'm providing very strong guarantees about the type of death reason, it's reasonable for users to discriminate based on type. Downcasting in Java has always been a bit of a code smell, on the basis that it can't possibly know every possible subclass of a class. The logic is "okay, you've handled cases X and Y, but what if someone comes along and writes class Z that you've never heard of". But that can't happen here. The class is sealed, so it's perfectly reasonable for someone to write a sort of pseudo-visitor that does one thing for "death by entity" and another for "death by other", since Java (or Kotlin, in my case) can be fully confident that there are not, and never will be, any other possibilities.
This makes more sense as well if you've used algebraic data types in Haskell or OCaml. The sealed keyword originated in Scala as a way to encode ADTs, and they're exactly what I just described: a type defined as the (tagged) union of a finite number of possible collections of data. And in Haskell and OCaml, it's entirely normal to discriminate on ADTs as well using match (or case) expressions.
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.
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.
In Head First Design Patterns, it was mentioned that you should code to an interface instead of an implementation however the last part of the code example got me confused. How is assigning the concrete implementation of an object at runtime a better design?
Does it mean that its better to put the instantation of the objects within a method in the class that uses the supertype? (a method whose purpose is specifically returning an object to a variable of the superclass)
//Programming to an implementation would be:
Dog d = new Dog();
d.bark();
//Programming to an interface/supertype would be:
Animal animal = new Dog();
animal.makeSound();
//Even better is assigning the concrete implementation at runtime: (says the book)
a = getAnimal();
animal.makeSound();
Even better way is to get the concrete class figured by someone else depending on the environment/context of your code execution. This is called Inversion of control/ dependency injection where the actual class is either configured in some configuration files or coding by convention is used to identify the correct file.
Coming back to why,imagine a project of moderate complexity where you have to talk to a DB. If you hard code the way to access a DB , you will end up asking customers to stick to a particular type/version of the DB. This is how JDBC works. Similarly for more complex scenarios, imagine moving from Db based system file based. Once you get that software should be designed for flexibility, its easy to appreciate the delayed initialisation of concrete classes.
If I were to say why in one word, then it would be: Centralization.
What I mean by this, is that you assign those concrete types at the start of your application somewhere in a single place and provide them to the classes that need them as interfaces, so those classes don't get coupled to the concrete types themselves but rather rely on those abstractions or interfaces.
This is similar to using the Factory pattern, so you don't spread object creation through out the program but rather in a single spot, which is easy to modify in the future.
This also enables you to use Dependency Injection and Inversion of Control which in turn comes with a bunch of good stuff like better testing, maintainability, run-time configuration, etc .
When I was programming a Form Validator in PHP, when creating new methods, I needed to increase the number of arguments in old methods.
When I was learning Java, when I read that extends is to not touch previously tested, working code, I thought I shouldn't have increased the number of arguments in the old methods, but overridden the old methods with the new methods.
Imagine if you are to verify if a field is empty in one part of the form, in an other and in yet an other.
If the arguments are different, you'll overload isEmpty, but, if the arguments are equal, is it right to use isEmpty, isEmpty2, isEmpty3, three classes and one isEmpty per class or, if both are wrong, what should I have done?
So the question is:
If I need different behaviors for a method isEmpty which receives the same number arguments, what should I do?
Use different names? ( isEmpty, isEmpty2, isEmpty3 )
Have three classes with a single isEmpty method?
Other?
If that's the question then I think you should use:
When they belong to the same logical unit ( they are of the same sort of validation ) but don't use numbers as version, better is to name them after what they do: isEmptyUser, isEmptyAddress, isEmptyWhatever
When the validator object could be computed in one place and passed around during the program lifecycle. Let's say: Validator v = Validator.getInstance( ... ); and then use it as : validator.isEmpty() and let polymorphism to it's job.
Alternatively you could pack the arguments in one class and pass it to the isEmpty method, although you'll end up with pretty much the same problem of the name. Still it's easier to refactor from there and have the new class doing the validation for you.
isEmpty( new Arguments(a,b,c ) ); => arguments.isEmpty();
The Open/Closed Principle [usually attributed to Bertrand Meyer] says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". This might be the principle that you came across in your Java days. In real life this applies to completed code where the cost of modification, re-testing and re-certification outweighs the benefit of the simplicity gained by making a direct change.
If you are changing a method because it needs an additional argument, you might choose to use the following steps:
Copy the old method.
Remove the implementation from the copy.
Change the signature of the original method to add the new argument.
Update the implementation of the original method to use the new argument.
Implement the copy in terms of the new method with a default value for the argument.
If your implementation language doesn't support method overloading then the principle is the same but you need to find a new name for the new method signature.
The advantage of this approach is that you have added the new argument to the method, and your existing client code will continue to compile and run.
This works well if there is an obvious default for the new argument, and less well if there isn't.
Since java 5 you can use variable list of arguments as in void foo(Object ... params)
You will need to come up with creative names for your methods since you can't overload methods that have same type and number of arguments (or based on return type). I actually personally prefer this to overloading anyway. So you can have isEmpty and isEmptyWhenFoo and isEmptyWhenIHaveTheseArguments (well meybe not the last one :)
Not sure if this actually answers your question, but the best way to think about OO in "real life" is to think of the Nygaard Classification:
ObjectOrientedProgramming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
So how would you build a physical device to do what you are trying to do in code? You'd probably have some kind of "Form" object, and the form object would have little tabs or bits connected to it to represent the different Form variables, and then you would build a Validator object that would take the Form object in a slot and then flash one light if the form was valid and another if it was invalid. Or your Validator could take a Form object in one slot and return a Form object out (possibly the same one), but modified in various ways (that only the Validator understood) to make it "valid". Or maybe a Validator is part of a Form, and so the Form has this Validator thingy sticking out of it...
My point is, try to imagine what such a machine would look like and how it would work. Then think of all of the parts of that machine, and make each one an object. That's how "object-oriented" things work in "real life", right?
With that said, what is meant by "extending" a class? Well, a class is a "template" for objects -- each object instance is made by building it from a class. A subclass is simply a class that "inherits" from a parent class. In Java at least, there are two kinds of inheritance: interface inheritance and implementation inheritance. In Java, you are allowed to inherit implementation (actual method code) from at most one class at a time, but you can inherit many interfaces -- which are basically just collections of attributes that someone can see from outside your class.
Additionally, a common way of thinking about OO programming is to think about "messages" instead of "method calls" (in fact, this is the original term invented by Alan Kay for Smalltalk, which was the first language to actually be called "object-oriented"). So when you send an isEmpty message to the object, how do you want it to respond? Do you want to be able to send different arguments with the isEmpty message and have it respond differently? Or do you want to send the isEmpty message to different objects and have them respond differently? Either are appropriate answers, depending on the design of your code.
Instead having one class providing multiple versions of isEmpty with differing names, try breaking down your model into a finer grained pieces the could be put together in more flexible ways.
Create an interface called Empty with
one method isEmpty(String value);
Create implemntations of this
interface like EmptyIgnoreWhiteSpace
and EmptyIgnoreZero
Create FormField
class that have validation methods
which delegate to implementations of
Empty.
Your Form object will have
instances of FormField which will
know how to validate themselves.
Now you have a lot of flexibility, you can combine your Empty implemenation classes to make new classes like EmptyIgnoreWhiteSpaceAndZero. You can use them in other places that have nothing to do with form field validation.
You don't have have have multple similarly named methods polluting your object model.