is there a design pattern that I can make an object to have some kind of state where he starts as an extended object, but after some time turn back to its super.
For example - partial file inherits from a file and after its completed it goes to be a file.
No there is no type mutation in Java (and to be fair I can't think of any modern language having it).
What you may do, but it's clearly not exactly the same :
using a constructor taking your object as a parameter to build a new object in a different class (just like you can do new Float(new Double(2));). Note that this doesn't change the initial object so you have to assign again the variable(s) holding it.
add a type variable, based on an enum, indicating what's the nature of the object. For most purposes it's enough (and will save you from building an heavy type hierarchy).
Now, do you need type mutation ? If you just need to handle your object as if it was a direct instance of its superclass, you can do it already. The main difference with type mutation is that you call the overridden methods but that's normally fine if the type hierarchy was correctly designed.
And supposing I'd design a PartialFile class (supposing the name properly defines what it is), instead of using inheritance I would have used composition : I would have made a decorative class whose instance would have had a variable private File sourceFile.
This question is flawed - an extended Object is always an instance of its super class.
In your example, the following is valid...
public class PartialFile extends File{
// methods
}
PartialFile partFile = new PartialFile();
// do operations on partFile
File file = partFile;
// do operations on file
Because PartialFile extends File, you don't really need to 'turn it into its super class' - it already is an instance of the super class.
You can think of the PartialFile object as being a PartialFile, a File, an Object, and any other classes that it extends, all at the same time. You don't need to turn it between these different class types - just use it directly. For the above code, if you want to call the File.rename() method, both the following statements will do the same thing...
partFile.rename();
file.rename();
You don't need to change the partFile into a file to use the methods of the File object - just use them directly, as the Java VM knows that a PartialFile is also a File.
You can't really change a sub-type to be its super type - the Java VM will always know what type it really is - but you can trick it. If you use the following code...
PartialFile partFile = new PartialFile();
// do operations on partFile
File file = partFile;
// do operations on file
and then only every use file instead of partFile, you won't be able to use any of the PartialFile methods on it. It kinda disguises that its a PartialFile, but it doesn't actually convert it.
If you do something like this...
public File createFile(){
PartialFile partFile = new PartialFile();
// operations on partFile
return partFile;
}
File file = createFile();
// operations on file
You can create and use a PartialFile in the method, but when you're finished you return it as a simple File. Whenever you refer to this object from now on, the Java VM will pretend that its a File. However, technically it will always be a PartialFile, and it doesn't stop you casting it back into a PartialFile if you want to, like so...
PartialFile partFile = (PartialFile)file;
// operations on partFile
So its just a disguise.
A subclass is already an instance of its superclass, so you can just cast it to its superclass
class PartialFile extends File {
// Code...
}
PartialFile partialFile;
// Code...
File file = (File) partialFile;
Use design pattern State and/or a Factory method.
You may still have to do some refactoring, as you would most likely need an Interface/abstract base class for the super.
Something like this:
class MySwitcher implements SuperInterface {
private final SuperInterface super = new Super();
private final SuperInterface subclass = new Subclass();
private SuperInterface current = super; // Start in state "behaves as super"
// Method from SuperInterface
public MyResult doAction(final MyData d) {
final MyResult res = current.doAction(d);
current = setImplementationBasedOnResOfDoAction(res);
return res;
}
}
Related
I'm doing some work with jesque, workers and pipelines. I'm ok with that; the thing is that I have a new feature. I have a class named FileAnalysis, so it has some common attributes, but it is not abstract enough; it is still very focused on the task it was made for.
I made another feature before and was able to reuse this FileAnalysis. But this time there are new key properties for the feature I'm working on, so I created a new object ContactFileAnalysis with the additional properties.
A FileAnalysis consists of the main object, which is then parsed to JSON and stored in redis. This is done through a manager; this manager reads/writes to redis, and recreates the FileAnalysis object. There is a support object to update the state of the file analysis in a pipeline; it's called:
FileAnalysisUpdater(FileAnalysis).
If I make a new manager which is able to handle ContactFileAnalysis, this objects holds new properties and the new manager will store them in redis correctly. Then it calls the updater in a pipeline. What I want to achieve is to invoke
ContactFileAnalysis contactFileAnalysis;
updater.Update((FileAnalysis) contactFileAnalysis);
When I cast to a parent object and the pipeline is done, will contactFileAnalysis be updated by the updater? Or does this cast change the object reference and therefore no change is reflected?
I want to reuse this functionality because there are no changes in it; the behavior is the same, the information is the same; I just need to propagate new information, and to do so I persist it in redis, but from there on it's the same; the updater doesn't need anything from my new object.
P.S.: I know it is safer to write every involved object again and make sure it works with the new FileAnalysis, but this means a lot of code for a feature that is hardly used and not that important. Also, I work for this project and it's not easy to approve a PR of 4k lines of code.
As user2864740 pointed out in a comment, casting an object reference never changes the reference. You can test this easily enough:
Object obj = null;
String str = "foo";
obj = (Object) str; // Unnecessary! See below.
System.out.println ("Is str == obj? " + (str == obj));
However, that casting to the parent is likely unnecessary. Hopefully you declared ContactFileAnalysis to be a subclass of FileAnalysis:
public class ContactFileAnalysis extends FileAnalysis
If so, then any reference to an instance of ContactFileAnalysis is always considered a reference to an instance of FileAnalysis. In fact, it's also a reference to an instance of FileAnalysis' superclass, and so on up the line (to java.lang.Object, the parent of all java objects). Which means my cast to Object in the sample code was unnecessary:
obj = str; // This works, and is considered proper style.
It's also unnecessary to cast it to pass it to updater.Update(). (Another style note: methods should start with a lowercase letter.)
updater.Update(contactFileAnalysis); // Probably fine. See below.
Note that if you didn't declare ContactFileAnalysis to be a subclass of FileAnalysis, you will have to cast it. (This could happen if you instead had a class that implemented two interfaces, had a reference to an instance of it typed to one of those interfaces, and wanted to pass it to a method that took an instance of the other.)
Another note: if for some reason you had two methods as follows:
public void update (FileAnalysis fa) { /* code */ }
public void update (ContactFileAnalysis cfa) { /* ugh */ }
And you made a reference to a ContactFileAnalysis instance, and passed that to your updater:
ContactFileAnalysis myCFA = new ContactFileAnalysis();
updater.update (myCFA);
It'll use the second update - the one defined to take a CFA. Cast it, however:
updater.update ((FileAnalysis) myCFA);
and it'll use the first update. Same thing happens if you set a FileAnalysis variable to it.
FileAnalysis myFA = myCFA;
updater.update (myFA); // uses the first update, even though it's a CFA
Hopefully you understand why. If not, check out the official documentation on inheritance.
I know this question has been asked a lot, but the usual answers are far from satisfying in my view.
given the following class hierarchy:
class SuperClass{}
class SubClass extends SuperClass{}
why does people use this pattern to instantiate SubClass:
SuperClass instance = new SubClass();
instead of this one:
SubClass instance = new SubClass();
Now, the usual answer I see is that this is in order to send instance as an argument to a method that requires an instance of SuperClass like here:
void aFunction(SuperClass param){}
//somewhere else in the code...
...
aFunction(instance);
...
But I can send an instance of SubClass to aFunction regardless of the type of variable that held it! meaning the following code will compile and run with no errors (assuming the previously provided definition of aFunction):
SubClass instance = new SubClass();
aFunction(instance);
In fact, AFAIK variable types are meaningless at runtime. They are used only by the compiler!
Another possible reason to define a variable as SuperClass would be if it had several different subclasses and the variable is supposed to switch it's reference to several of them at runtime, but I for example only saw this happen in class (not super, not sub. just class). Definitly not sufficient to require a general pattern...
The main argument for this type of coding is because of the Liskov Substituion Principle, which states that if X is a subtype of type T, then any instance of T should be able to be swapped out with X.
The advantage of this is simple. Let's say we've got a program that has a properties file, that looks like this:
mode="Run"
And your program looks like this:
public void Program
{
public Mode mode;
public static void main(String[] args)
{
mode = Config.getMode();
mode.run();
}
}
So briefly, this program is going to use the config file to define the mode this program is going to boot up in. In the Config class, getMode() might look like this:
public Mode getMode()
{
String type = getProperty("mode"); // Now equals "Run" in our example.
switch(type)
{
case "Run": return new RunMode();
case "Halt": return new HaltMode();
}
}
Why this wouldn't work otherwise
Now, because you have a reference of type Mode, you can completely change the functionality of your program with simply changing the value of the mode property. If you had public RunMode mode, you would not be able to use this type of functionality.
Why this is a good thing
This pattern has caught on so well because it opens programs up for extensibility. It means that this type of desirable functionality is possible with the smallest amount of changes, should the author desire to implement this kind of functionality. And I mean, come on. You change one word in a config file and completely alter the program flow, without editing a single line of code. That is desirable.
In many cases it doesn't really matter but is considered good style.
You limit the information provided to users of the reference to what is nessary, i.e. that it is an instance of type SuperClass. It doesn't (and shouldn't) matter whether the variable references an object of type SuperClass or SubClass.
Update:
This also is true for local variables that are never used as a parameter etc.
As I said, it often doesn't matter but is considered good style because you might later change the variable to hold a parameter or another sub type of the super type. In that case, if you used the sub type first, your further code (in that single scope, e.g. method) might accidentially rely on the API of one specific sub type and changing the variable to hold another type might break your code.
I'll expand on Chris' example:
Consider you have the following:
RunMode mode = new RunMode();
...
You might now rely on the fact that mode is a RunMode.
However, later you might want to change that line to:
RunMode mode = Config.getMode(); //breaks
Oops, that doesn't compile. Ok, let's change that.
Mode mode = Config.getMode();
That line would compile now, but your further code might break, because you accidentially relied to mode being an instance of RunMode. Note that it might compile but could break at runtime or screw your logic.
SuperClass instance = new SubClass1()
after some lines, you may do instance = new SubClass2();
But if you write, SubClass1 instance = new SubClass1();
after some lines, you can't do instance = new SubClass2()
It is called polymorphis and it is superclass reference to a subclass object.
In fact, AFAIK variable types are meaningless at runtime. They are used
only by the compiler!
Not sure where you read this from. At compile time compiler only know the class of the reference type(so super class in case of polymorphism as you have stated). At runtime java knows the actual type of Object(.getClass()). At compile time java compiler only checks if the invoked method definition is in the class of reference type. Which method to invoke(function overloading) is determined at runtime based on the actual type of the object.
Why polymorphism?
Well google to find more but here is an example. You have a common method draw(Shape s). Now shape can be a Rectangle, a Circle any CustomShape. If you dont use Shape reference in draw() method you will have to create different methods for each type of(subclasses) of shape.
This is from a design point of view, you will have one super class and there can be multiple subclasses where in you want to extend the functionality.
An implementer who will have to write a subclass need only to focus on which methods to override
I need to have some sort of data structure that can contain heterogenous subclasses of the same superclass, all of which I have implemented myself.
So far, I am attempting to have an ArrayList<SuperClass> list = new ArrayList<SuperClass>();
and then, I am assuming I will be able to cast each slot of list into either of the subclasses, but this is not working out so well.
I need an efficient way to do the aforementioned.
Thanks!
You can do it with any data structure that exists, I would recommend a List or a Set. For instance:
Collection<Super> supers = new ArrayList<Super>();
Now when you say this:
I am assuming I will be able to cast each slot of list into either of
the subclasses,
That is an invalid assumption. The collection will hold any object that extends Super however you cannot arbitrarily cast each element into whatever you want. You would need to do an instanceof test on each element if you are looking for that type of functionality, example follows:
for(Super currentSuper : supers)
{
if(currentSuper instanceof SubA)
{
SubA subA = (Suba) currentSuper);
// do stuff with subA
}
else if(currentSuper instanceof SubB)
{
SubB subB = (SubB) currentSuper);
// do stuff with subB
}
}
Scope as need be.
Now on the point of Vlad:
and much better design would be not to test what the actual class is,
but just to call a virtual method, which will do the right thing in
any case
If you can guarantee the functionality of all potential sub-classes and have no issues with people overriding your classes (in the event you haven't marked them final) you do not need to do the instance of test. Instead your code could be as simple as:
for(Super currentSuper : supers)
{
currentSuper.doSomethingNifty();
}
I don't really understand how the class keywords work in some instances.
For example, the get(ClientResponse.class) method takes the ClientResponse.class. How does it use this when it gets it, and what are the advantages over just passing an instance of it?
SomeClass.class
returns a Java Class object. Class is genericized, so the actual type of SomeClass.class will be Class<SomeType> .
There are lots of uses for this object, and you can read the Javadoc for it here: http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html
In ClientResponse.class, class is not a keyword, neither a static field in the class ClientResponse.
The keyword is the one that we use to define a class in Java. e.g.
public class MyClass { } /* class used here is one of the keywords in Java */
The class in ClientResponse.class is a short-cut to the instance of Class<T> that represents the class ClientResponse.
There is another way to get to that instance for which you need an instance of ClientResponse. e.g
ClientResponse obj = new ClientResponse();
Class clazz = obj.getClass();
what are the advantage over just passing a instance of it?
In the above example you can see what would happen in case obj was null (an NPE). Then there would be no way for the method to get the reference to the Class instance for ClientResponse.
The Class class, which is different from the class keyword, is meta-data describing instances. It tells you about the methods, data members, constructors, and other features of the instances that you create by calling new.
For example get(ClientResponse.class) method takes the
ClientResponse.class how does it uses this when it gets it and what
are the advantage over just passing a instance of it?
You can't pass an instance of ClientResponse to this method; it's expecting meta-data about all instances of ClientResponse. If you passed an instance, you'd expect that the method might change the state of that instance. But passing the meta-data about all instances might allow the method to create a new kind of instance (e.g. a dynamic proxy) or do something else that depends on the meta-data about all instances of ClientResponse. See the difference?
A class is a "blueprint" of the object. The instance is a object.
If we have
public class SomeClass {
int a;
SomeClass(int a) {
this.a = a
}
}
We can have an instance of this class
SomeClass c = new SomeClass(10);
c is an instance of the class. It has a integer a with value 10.
The object SomeClass.class represents a Class.
Here SomeClass.class is a object of the type Class which has the information that SomeClass is
a concrete class with
one constructor
with a integer member variable
and lots more other metadata about the class SomeClass. Note that it does not have a value for a.
You should use get(c) incase you are planning to do something with a instance of c like call c.a or other useful functions to manupulate/get data of the instance.
You should use get(SomeClass.class) when the get returns something based on the fact that the argument is some type of class. For example, if this is a method on a Registry class which has a map which retrieves a implementation class based on type of class passed in.
The very most important fact is - you don't need to have an instance to call the method. It's critically useful in situations when you cannot for some reason instantiate a class, e.g. it's abstract, or have only private constructor, or can only be correctly instantiated by some framework, like Spring or JSF.
You can then call get to obtain an object of a requested type without even knowing where it does come from and how it get's created.
Here ClientResponse.class is an instance of Class<ClientResponse>. In general Class object represents type of an object. When you create new instance:
Object obj = new ClientResponse()
you can retrieve the class (type) of that object by calling:
obj.getClass()
So, why would you pass Class objects around? It's less common, but one reason is to allow some method create arbitrary number of instances of a given class:
ClientResponse resp = ClientResponse.newInstance();
There's a lot of ways Class objects can be used. This is used for Reflection. Below is a link that can help you understand more.
http://docs.oracle.com/javase/tutorial/reflect/class/classNew.html
Whenever we compile any Java file, the compiler will embed a public, static, final field named class, of the type java.lang.Class, in the emitted byte code. Since this field is public and static, we can access it using dotted notation along with class name as in your case it is ClientResponse.class.
I need to write a function that accepts an object , but I want to enforce in the function call (not after the function is called) that the object is an interface.
Meaning , I want to make sure this is an Interface at compile time , not on run time.
What do I mean?
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
In this example , the passed object is an interface , and I want that the MyClass.register function to enforce the this requirment in it's declaration.
I don't know which interface I'm going to get , and there is no use defining another interface to be implemented by all other implementation , because I need the real interface.
To accept only objects that implement an interface as argument, use the interface as type, i.e.:
void acceptMaps(Map argument) {
}
can be called with objects implementing the Map interface, like HashMap but not with Strings for instance as they do not implement Map.
Is this what you meant with your question?
Edit in this example, objects implementing SortedMap which extends Map are accepted too, so in your case you could create a BaseInterface and extend that in the interfaces (like AcceptedInterface extends BaseInterface) you want to be accepted by your .register(BaseInterface arg) method.
You can't instantiate an interface so you would never be able to create one to send in. You can specify an interface in the parameters for the function and only objects which implement that interface can be passed in. But there is no way to require an interface be what is passed in because you can't create them.
I think you need to rethink what you're trying to accomplish.
You're making a distinction between the type of the object (in this case A) and the type of the reference to the object (in this case ISomething).
Sounds like you want to permit this code:
ISomething something = new A();
MyClass.register(something);
but forbid this code:
A something = new A();
MyClass.register(something);
I don't think you can achieve this with Java.
Let me see if I understand.
Do you want to check at compile time that the argument passed to a function is some interface? Any interface?
If that's the question, the answer is you can't.
I don't know which interface I'm going to get [...] I need the real interface.
You can't actually validate if you don't know which type to expect.
In Java you need to know the type to validate the parameter, the argument must be of the same type or a descendant, Java doesn't make distinctions on this regard at compile time, you can make it at runtime as Daff aswered.
You can ask the class of the object you get interfaces it implements during runtime.
If you can't already give the compiler the types of the interfaces you expect it has no way to predict what is going to be passed into your method so you will have to use runtime reflection.
There's no way to check at runtime, if the 'object is an interface' because an object can never ever be 'an interface', it only be an instance of a class that implements an interface.
And it's not possible to restrict a method signature to interface usage, say you'll allow type 'Animal' but not type 'Dog' which implements animal behavior. (I guess that's what you were looking for)
Taking your example - you want a compiler error for this implementation:
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
A unwanted = (A) something;
MyClass.register(unwanted); // <- compilation error here
But practically spoken - I see no immediate reason. If you want to enforce programmers to use interfaces - user code inspection or quality check tools. If you want to restrict instantiation of an implementation, protect the constructor and use a factory to produce instances.
"The object is an interface" doesn't make sense. It seems like you want to enforce that the pointer passed into the function was declared with an interface type like
Interface_t x = new Class_which_implements_interface_t();
as opposed to
Class_which_implements_interface_t y = new Class_which_imlements_interface_t();
The only problem is that if you make a function like this:
void some_func(Interface_t z) {...}
And you call it with some_func(x); or some_func(y); the function is passing the reference by value, which means that inside of some_func, z is a copy of x or y which has been casted to an Interface_t pointer. There is no way to get information about what type the original pointer had. As long as it is able to be casted to an Interface_t it will compile and run.