First suppose that I have an abstract class, let's call it AbstractClass. Suppose
public abstract AbstractClass {
public abstract void F();
}
Suppose that I have a class, let's call it ClassA. ClassA extends AbstractClass. ClassA is saved in a folder. (It has to be loaded onto the classpath.) Now suppose that I am writing a new class within the program,
ClassB
and I want ClassB to be able to reference ClassA. Something along the lines of
public class ClassB extends AbstractClass {
ClassA A = new ClassA();
public void F() {
A.F();
}
}
Now, I have had no trouble using a class loader to get classA and use it dynamically. I have also had no problem writing a class like ClassA dynamically based on user input, compiling it within the program (using ecj.jar), and then loading it and calling methods from it.
I cannot figure out though how to reference a dynamically loaded class in a class that I am now writing and compiling dynamically. I don't know how to write the import, etc. Loading classA and putting
import classA;
into the classB.java file does not do the trick.
This is my first question on StackOverflow (long time reader), so go easy on me. Thanks in advance.
--
Context: A program that uses probability distributions entered by the user. I have an abstract class AbstractDistribution which has abstract methods for the distribution's CDF, PDF, inverse CDF, etc. So far this has worked well, dynamically writing compiling and loading distributions that extend AbstractDistribution, getting newInstance() of them and using them like any other class. However, if I have written and dynamically loaded a distribution Dist1, I want to be able to write a Dist2 that can call (for example), the PDF of Dist1.
Don't make B refer to A directly - make B refer to AbstractClass and take a reference to an instance in its constructor:
public class ClassB extends AbstractClass {
private final AbstractClass other;
public ClassB(AbstractClass other) {
this.other = other;
}
public void F() {
other.F();
}
}
At this point you need to work out how you're going to get hold of a reference to the other instance of AbstractClass (whether it's a ClassA or something else) but it does get rid of the direct dependency.
I'm sure there will be more exact details to work out, but if you can break the direct dependency like this, it should make the dynamic compilation aspect less of a problem.
Related
Suppose I have these classes:
public class ChildClass extends ParentClass
{
// some class definition here
}
public abstract class ParentClass
{
public static void printClass()
{
// get the class that extends this one (and for example, print it)
}
// some class definition here
}
Lets say when calling ParentClass.printClass() I want to print the name of the class (like doing System.out.println(ParentClass.class)). When then extending ParentClass (for example like in ChildClass) and calling ChildClass.printClass(), I want it to print the name of the extending class (like doing System.out.println(ChildClass.class)). Is this somehow possible?
I've found a way to get the class from inside a static method by using MethodHandles.lookup().lookupClass(), but when using it inside of ParentClass.printClass and extending ParentClass, then calling printClass on the extending Class, I always get the class of ParentClass.
static methods are best thought of as living entirely outside of the class itself. The reason they do show up in classes is because of the design of java (the language) itself: Types aren't just types with a hierarchy, they also serve as the primary vehicle for java's namespacing system.
Types live in packages, packages are the top level namespace concept for types. So how do you refer to a method? There's only one way: Via the type system. Hence, static methods do have to be placed inside a type. But that's about where it ends.
They do not inherit, at all. When you write:
ChildClass.lookupClass()
The compiler just figures out: Right, well, you are clearly referring to the lookupClass() method in ParentClass so that is what I will compile. You can see this in action yourself by running javap -c -p MyExample. The same principle applies to non-static methods, even.
For instance methods, the runtime undoes this maneuvre: Whenever you invoke a method on any object, the runtime system will always perform dynamic dispatch; you can't opt out of this. You may write:
AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);
and you can use javap to verify that this will end up writing into the class file that the method AbstractList::sort is invoked. But, at runtime the JVM will always check what list is actually pointing at - it's an instance of ArrayList, not AbstractList (that's obvious: AbstractList is abstract; no object can ever be directly instantiated as `new AbstractList). If ArrayList has its own take on the sort method, then that will be called.
The key takeaway of all that is: Static methods do not inherit, therefore, this dynamic dispatch system is not available to them, therefore, what you want cannot be done in that fashion.
So what to do?
It feels like what you're doing is attempting to associate a hierarchy to properties that apply to the class itself. In other words, that you want there to be a hierarchical relationship between the notion of 'ParentClass's lookupClass method and ChildClass's lookupClass method - lookupClass is not a thing you ask an instance of ChildClass or ParentClass - you ask it at the notion of the these types themselves.
If you think about it for a moment, constructors are the same way. You don't 'ask' an instance of ArrayList for a new arraylist. You ask ArrayList, the concept. Both 'do not really do' inheritance and cannot be abstracted into a type hierarchy.
This is where factory classes come in.
Factory classes as a concept are just 'hierarchicalizing' staticness, by removing static from it: Create a sibling type to your class hierarchy (ParentClassFactory for example):
abstract class ParentClassFactory {
abstract ParentClass create();
abstract void printClass();
}
and then, in tandem with writing ChildClass, you also write ChildClassFactory. Generally factories have just one instance - you may want to employ the singleton pattern for this. Now you can do it just fine:
class ChildClassFactory extends ParentClassFactory {
private static final ChildClassFactory INSTANCE = new ChildClassFactory();
public static ChildClassFactory instance() { return INSTANCE; }
public ParentClass create() { return new ChildClass(); }
public void printClass() { System.out.println(ChildClass.class); }
}
// elsewhere:
// actually gets the ChildClassFactory singleton:
ParentClassFactory factory = ....;
factory.printClass(); // will print ChildClass!
Quoting #RealSkeptic:
Static methods are not inherited. The fact that you can call ChildClass.printClass() is just syntactic sugar. It actually always calls ParentClass.printClass(). So you can't do something like that with a static method, only an inheritable non-static one.
im trying to create my little library. But i have little problem. I cant right understand how to hide some classes/methods from public usage.
Say i have structure :
-myPackage.com
-classA (public class example : public classA {...})
-classB (just a class example : class classB {...}
in this way when i add my aar file to android project. I can use from library only classA. classB hided(invisible for developer) and i cant call him (its ok). But classA can use functions from classB . Because its in same package. And its ok.
So how correctly create classes in another packages ?
-myPackage.com
-myHelpPackage
-classC (public class example: public class classC {...}
-classD (just a class example: class classD {...}
-classA (public class example : public classA {...})
-classB (just a class example : class classB {...}
in this way i have two public classes which developer can call
classA
classC
classD visible only for classA. So i cant call classD(functions) from classA.
Main question : how to achive it ?
I want to have only one classA to call. classC is ok. classD and classB should be invisible for developer. But visible only for classA. Anyone can help me with this ?
If you don't specify any access level modifier, e.g.:
package myPackage.com
class classA {
}
then the class will be package-private by default.
This means it is only visible to classes inside your package.
See also the documentation by Oracle here
This question has been answered in the comments by JakobJeremais, but in case it's not clear to anyone, or they skip over it because they only read top-level answers (understandable). If you have a package-private class in your aar, it will still be publicly accessible, so I would recommend nesting the class in whatever calls it, an you will be safe.
For instance, I had to extend EditText so that I could override just one method, and nothing else. Then I had to reference that from only one other class, but didn't want it accessible from whatever projects I added my library to. So I nested it, and now it's fine.
public class VisibleClass extends View {
public static HiddenClass extends EditTextCompat {
#Override
public void annoyingFunction() {
//Disable this function
}
}
}
I should note, though: The compiler isn't happy about accessing it from layout, so I suppose it hasn't really helped, so I wouldn't recommend it, for now. If you have time to tinker, go ahead, though.
I am stuck with a programming problem:
I have two Java projects, in my Eclipse IDE: ProjectA, and ProjectB.
ProjectB references ProjectA
I have declared a class in ProjectA: ClassA, and one in ProjectB: ClassB, such that:
public class ClassA{
public static Object foo(){
//blah
}
}
public class ClassB extends ClassA{
public static Object foo(){
//blah
}
}
I also have a class called ClientClass, in ProjectA. This ClientClass earlier used to create an instance of ClassA and use it. But now, based on an environment setting, the ClientClass should be provided the option to use ClassA or ClassB.
This seemed to be a problem for the AbstractFactory pattern, or so I thought.
I need to create a Factory that provides access to ClassA or ClassB. ClientClass should not be aware that it is ClassA or ClassB. This requires me to create an interface for ClassA and ClassB.
Issues I ran into:
ClientClass cannot refer to ClassB directly (no import statements / or new invocation), because ClassB is in a different project. This may be an Eclipse IDE restriction, but it also makes sense to me when viewing these two projects as jar files. A cyclic relationship is avoidable.
I cannot create a Factory interface and a common interface for ClassA & ClassB, and then via the AbstractFactory pattern provide a ClassAFactory or a ClassBFactory. This is because the methods to be invoked on ClassA and ClassB are static ones. The methods on these classes would need to be present on the interface. But then, in Java, one can't have an "abstract static" modifier
Can anyone suggest an elegant solution for this problem?
Well, there are a number of problems here. For starters, and this is the biggest one, this isn't going to work because you can't override static methods in Java. The goal, I think, of what you're saying is to be able to substitute, at run time, ClassA for ClassB or B or A or whatever, depending on some parameters. In order to do that, you need to be able to take advantage of dynamic dispatch (or, simply put, virtual methods) that would allow the runtime system to select the memory address of the method to be executed at run time. This isn't possible with static methods. You need to make the methods nonstatic for this to work. You don't have to specifically design a Java Interface but when you extend ClassA with ClassB, you'll be able to treat your objects as if they are simply a ClassA object.
All of that said, if you remove the static modifiers from the methods and make them nonstatic, then you could use ClassB in project A without having any import statements what-so-ever in the client class you're talking about. However, somewhere in project A, somebody is going to need to be aware of ClassB in order to instantiate it. That is, of course, unless you want to do some runtime binding stuff and load the class dynamically using a string. Does that make sense?
Firs problem: Your Class B and Class A's foo method is static. Hence nothing is being overriden. You should not make them static if you intend to override foo in ClassB.
The second problem here is that upstream needs to be aware of the downstream. That is just wrong isn't it?
The question of whether this is an abstract factor pattern or not is besides the point. Design patterns just make code follow a known structure. It is not an end in itself.
For now, why is it that your ClientClass in Project A needs to know about ClientB?
As for the factory, your factory needs to be in Project B and it can be something like:
class Factory {
public static ClassA createTheRightOne(EnvironmentSettings settings) { //do the right thing }
}
once you fix the static modifier
Pavan
class arijit
{
public static void main(String args[])
{
System.out.println("Base class main");
amit ab=new amit(); //how is it possible as the sub class object also holds base class
ab.a();
ab.ma();
}
public void m()
{
System.out.println("Base class method");
}
}
class amit extends arijit
{
public void a()
{
System.out.println("Sub Class method");
m();
}
}
The crux of your question seems to be that you're creating an instance of the amit class within the main method of its base class, arijit, and you're wondering how that's possible.
Why wouldn't it be possible? Your main method references the subclass by name, so it's just like any other class from that point of view. You can do it in non-static members, too, if you like.
Architecturally, it usually indicates that there's a problem with your structure if the base class knows the intimate details (like the names) of its subclasses; that's not the usual way 'round of things.
Perhaps you need to distinguish compile time from runtime.
At compile time the structure of arijit is well-known. It does not matter that halfway in the class, in main, a subclass is used, as that is a runtime thing.
But I admit, the Java compiler is not all that stupid :)
When you compile your program two .class files are formed,namely arijit.class and amit.class.
So when your program is being interpreted ,interpreter knows about both the .class files and hence you can create Objects like that.
Its simple as you can create an object in the class of the same class type, you can create its subclass type too.
The place you can't create a sub-class in the parent class is in the constructor.
I have to implement a logic whereby given a child class, I need to access its parent class and all other child class of that parent class, if any. I did not find any API in Java Reflection which allows us to access all child classes of a parent class. Is there any way to do it?
For example:
class B extends class A
class C extends class A
Now using class B, I can find the superclass by calling getSuperClass(). But is there any way to find all the child classes once I have the parent class i.e. class B and class C??
If this wasn't homework (where 3rd party librares are probably not allowed), I would have suggested Google Reflections' Reflections#getSubTypesOf().
Set<Class<? extends A>> subTypes = reflections.getSubTypesOf(A.class);
You can do this less or more yourself by scanning the classpath yourself, starting with ClassLoader#getResources() wherein you pass "" as name.
You are correct: there is no direct API for this. I guess you could scan all loaded classes and see if they are a subclass of a given class.
One problem: you'll only able to find classes that are already loaded. None of these methods will find classes that haven't been loaded yet.
You can use:
thisObj.getClass().getSuperclass()
thisObj.getClass().getInterfaces()
thisObj.getClass().getGenericInterfaces()
thisObj.getClass().getGenericSuperclass()
I recently coded something to scan the members of a class and if those were non-primitives scan those as well. However, I did not traverse upwards so I didn't use the above methods but I believe they should do what you want.
EDIT:
I ran a simple test with the following:
public class CheckMe {
public CheckMe() {
}
}
public class CheckMeToo extends CheckMe {
public CheckMeToo() {
}
}
// In main
System.out.println( CheckMeToo.class.getSuperclass() );
// Output
class CheckMe
After that it's a matter of coding the traversal. If its parametrized then things may get a little complicated but still quite doable.
EDIT: Sorry didn't read carefully, let me look further into it.
EDIT: There doesn't seem to be any way to do it without scanning everything in your CLASSPATH and checking to make sure an object is an instance of some class.