Android: extends from multiple classes - java

I have an application with the name MyApplication that extends from library application RoboInjectableApplication
public class MyApplication extends RoboInjectableApplication {
}
But now I want MyApplication to extends from another library application XWalkApplication so that my application have extension from RoboInjectableApplication and XWalkApplication how to achieve that

This is not possible Java only allows one super class. You may check the source codes of both classes and write a merged class which has all compatibilities.
If you would need a different super class in a different context you may try the flavors of Android Studio. There you can override classes which generates a different APK.

In java you can extend only one class.
You can check if you can use class field (variable) to have XWalkApplication functionality - this is often called composition.
Another way is as already suggested, you can merge the source code.
Another way is to play with interfaces if this is possible.

Multiple inheritence is not supported in java. It will cause ambiguity in few scenarios. One of the most common scenario is Diamond problem. You can read more about this from here.
In short it is not possible to extend from multiple classes.

Related

Prevent dependency on a class in Java / Kotlin, but allow extending

I wish to create a useful base Java class with a few protected methods and hooks so subclasses can be easily implemented.
However, I wish this class to ONLY be available for deriving a subclass, but not available as a dependency.
The reason is to prevent some junior/careless developers from coupling their code to this base class.
For example, if my base class is called BaseActivity.java, anyone can create their own
public class MyNewActivity extends BaseActivity
But no one can refer directly to BaseActivity with a field or method signature, for example this should not be allowed:
public void doSomethingOnBaseActivity(BaseActivity activity);
private BaseActivity someField;
public BaseActivity getActivity();
Is there any way to accomplish such a restriction in Java?
Maybe in Kotlin this would be possible?
EDIT:
This is NOT a duplicate of Kotlin: Can an abstract super class have an abstract constructor?.
I wish to prevent dependency on the base class, not just instantiation. "Abstract" doesn't help here.
No, this is not possible. This answer is true for all types, whether abstract or not, interface or class. When you are in the scope of a class (e.g. same package), and this class is not sealed then everybody in this scope can inherit it. As long you are inside the scope, you can reference this type. That's the point of access modifiers. It doesn't make sense to allow extension of a type but not referencing it. This contradicts the concept. Why would you want to do that? You can't remove that base class anyway because that would break the code of all inheritors. There is no point in allowing extension but disallowing referencing. What is the reason for this. Maybe there is a different way to accomplish your goal. The very moment somebody inherits from a type creates the dependency. This dependency is called inheritance. The subtype is a supertype. You can't hide this fact from the compiler.
If you want to omit a dependency but reuse code or provide a template of the code then don't use a type. You could use file templates or a code generator to generate the reusable code (like code snippets).
First off, let's address the why. Why are you looking for this? You're looking for a way to prevent the consumer from calling unwanted methods on a base class.
If you think you're looking for something else, think again. If you just want to hide it, think again. The end user will not care about implementation details at all.
If you created the base class, then don't publish an API that allows this in the first place. There was a chapter on this specifically in Clean Code.
If your base class extends another base class you're in trouble. You can't hide already published API, if you're extending and not encapsulating.
I wish this class to ONLY be available for deriving a subclass, but not available as a dependency. Is there any way to accomplish such a restriction in Java? Maybe in Kotlin this would be possible?
No. This is not an opinion, this is by design.
There may be a convoluted way to hide methods of parent classes but not on the class the consumer interacts with (extends).
You could have several layers of base classes each within its own Gradle module and setup implementation type dependency but then If you can extend the class, if you can see it, reference it, you can also use it anywhere.
Imagine this:
consumer module -> ConsumerActivity extends ExtensibleActivity
your library module -> ExtensibleActivity extends BaseActivity
your base library module -> BaseActivity extends Activity
Android SDK -> Activity
Consumer module only sees what's inside "your library module". It knows about ExtensibleActivity but it can't see any of its super types. The consumer can still reference ExtensibleActivity and its methods. The side effect is because the superclasses are not known from consumer's point of view, you can't pass an instance of ExtensibleActivity as an Activity because the type system doesn't know it extends an Activity, because it doesn't see the BaseActivity intermediary type. Here's a graph of what the consumer sees:
ConsumerActivity -> ExtensibleActivity -> BaseActivity (doesn't exist) -> ??? (don't know)
At this point you just have to ask yourself "should this have extended Activity in the first place?".
This is just terrible to work with. Lot of wasted effort for something that you shouldn't need to worry about.
If you want to conceal something, use composition over inheritance. Put your logic inside a Fragment or, better yet, put your logic inside a custom lifecycle aware component. That way you're in total control over the API. Make it so you don't have to worry about where it gets called from.
Write good documentation for your code and a usage manual.
And kindly allow me to break your damn library if I choose to use it incorrectly.
Do you have multiple methods in your API? Great! Nobody will prevent me from calling them out of order. You can write in your manual how it's supposed to be used, but ultimately, I'm writing my program, using your library, and if I do it wrong, then it's my fault when it breaks. This is fine.

Is it possible to extends 2 different classes in Java?

I am working on a project on SoftKeyboard. I am editing the sample codes provided with the Eclipse ADT bundle. I realised it is already extends InputMethodService. However, I want to attach a ContextMenu in the soft key.
Therefore in this case, I need to extend Activity too. How do i solve this problem?
No, java does not support Multiple inheritance, Why because the child can't know which parent it has to choose if extends more than one class. To over come this you have to go for Interface.
For more info refer this, this and this
You can use Strategy pattern:
link link
You should create interface, then your classes should implemented this interface like in example in second link.
Java does not support multiple inheritance.
You can try this workarounds:
1)Aggregation: make a class that takes those two activities as fields.
2)Interfaces.
3)Rethink your design

Extending a class--how do I avoid having to create multiple classes?

The question doesn't really make sense, but this should help explain it better.
I'm currently using the IOIO, and it works like this:
public class MainActivity extends CustomIOIOActivity {}
From there I can call classes I've made in CustomIOIOActivity, which extends Activity.
The problem I'm running into now is that I have to inherit classes different from just Activity. For example, FragmentActivity.
Is there a way for me to create a custom IOIO activity which I can use for when I extend Activity and FragmentActivity? I don't want to have to make two essentially identical classes, which is what I am doing right now--seems silly. I'm not very familiar with Java, perhaps this is easy to do.
In Java you can't inherit class from more than one superclass. In order to achive your purpose, I would advise you to move all common logic to another class(IOIOHolder, for example), which would take an Activity parameter in constructor. Later you can create two different classes extending Activity and FragmentActivity, each containing an exemplar of IOIOHolder and using it for it's own tasks. By using this approach you can write IOIO code once and use it in any activity you want.

Make a Java class have higher compile priority than one inside a library in IDEA

We have some portion of functionality packed in an external library and it is attached to our project. That library can't be changed in any way. Amongst others there are two classes lying inside it: com.myorg.Grandpa and com.myorg.Dad that extends com.myorg.Grandpa. Also there are com.myorg.Grandson extending com.myorg.Dad and a few other classes outside of the library extending com.myorg.Grandpa.
I decompile com.myorg.Grandpa class and add a new method new_method() to it.
Then I try to use new_method() in com.myorg.Grandson but IDEA won't let me do it cause Grandson extends Dad which extends library's Grandpa which doesn't contain new_method().
I tried to delete Grandpa from library and surprisingly IDEA didn't say a word and successfully compiled a project despite of the fact that in the boundaries of a library Dad extends non existing class.
The question is how to force Dad to extend a new Grandpa without deleting the one inside a library?
You could
Add an abstract class between Dad and GrandSon: Extend Dad, and add your method in the sub class. Then derive GrandSon from that sub class.
Put an instance of Dad in a new class, and let your IDE create delegate methods to the aggregated Dad instance. Again add your new method to the new class.
There is another possibility:
If you have to modify classes in place, use aspectj to weave in code: aspectj changes the byte-code (it does not need source code) at run-time. This way you can add methods or fields.
The fact is that you are duplicating classes with full package signature, so you will get the one that the classloader loads first. I know that in Websphere you can tweak classloader priorities, but couldn't say in your case.
Anyway, why not just do it without decompiling? You are causing yourself hard coupling to an external library and bad practices (maybe copyright issues) by decompiling/customizing. Besides, if the library gets updated, you will run into trouble having to reconstruct your customized classes.
Options:
Create your own implementation, for instance:
Create an Interface that replicates all methods in Grandpa plus the one you need.
Extend Grandpa class and implement the added method from your interface, all other methods will be left intact.
Extend all other extending classes from your own class hierarchie.
Instead of using the libraries common class, use your Interface as naming
This way you are kind of creating your own interface to the library, if it changes, you know where to make changes.
You could even do it without the interface, it's kind of wrapping the functionality, it would depend on what you need to achieve.
Anyway, I would try to solve it by own code and not by messing up with the library, it is just not worth it to do such tricks, if a new Programmer takes the project, they will need a lot of time to find out why and how it behaves.
Now, there might be variations in how to structure the class hierarchie, but it would depend on the specific implementation you need, so you would have to post more detailed data on what the library is and what you're trying to add to it if you expect some more specific answer...
Regards
It has to appear first to the class loader.
IDEA should load your class first if is in your project. You may also try to create a separate library for your class and include it in your project.
See also: http://www.jetbrains.com/idea/webhelp/configuring-module-dependencies-and-libraries.html

Make a class extends another class at runtime

There is a library have a base class (let's call it CBase) that performs some tasks and one can create classes that extends this CBase class.
The behavior of the CBase is not enough for me, so I would like to create my own CBase class (let's call it MyCBase) that have the same methods and members but these methods don't do the same thing.
Until now everything is ok. But what blocks me is that I would like to replace CBase by MyCBase. However, I have a lot of classes that extend CBase and I don't want to change them all.
Is it possible to replace CBase by MyCBase at runtime ?
So that
public class A extends CBase {}
becomes
public class A extends MyCBase {}
Can I perform this using code enhancement ? (like we do to add methods to a class at runtime. Is it also possible to change inheritance this way ?)
Thank you for your help !
EDIT
I would like to write a plugin for a framework, this is why I would like to change inheritance at runtime. This way users of the framework can use my plugin without changing their source code (changing the inheritance of their classes from CBase to MyCBase)
EDIT 2
Is it possible to do like this: ?
CtClass cc = CtClass.forName("pkg.AClass");
cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
cc.compile();
I'm not expert. Probably you could extend ClassLoader. But I highly recommend don't do it. The replacement will touch many of your classes but it will be clear in code reading and app execution.
I think there is also room for architecture improvement since you have so many classes extend CBase. People are trying to remove dependencies from other libraries or keep it really small. Because in this case you could easily switch to another library or add your own functionality.
I dont think you can change the extends of a class at runtime. I would suggest to change the extends of the objects or build an interface, which contains all the things your need
Changing all derived classes is a simple matter, provided you control their source code:
Create a new class in your project. Call it CBase, and put it in the same package as the library class.
Use the rename/move refactoring of your IDE to rename CBase to MyBase. This will have the IDE rename all references to the renamed/moved class ...
Write the code for MyBase, extending from CBase.
If you can not do this (for instance because some derived classes are in a library you do not control), you replace the implementation of CBase with your own. Simply create a class of the same package and name in your project (the classloader searches the classpath in order, and uses the first class of the proper package and name it finds). This approach however is very brittle, as the compiler can not check binary compability between the old and new version of CBase. The JVM will check this compatibility when classes are loaded, but since classes are only loaded when needed, its hard to test your changes. (Which is why I do not recommend this approach if there are other options).
You could also change the classes as they are loaded my manipulating the class file, that that's going to be even more brittle, and the compiler would allow you to use any additional features MyBase might have. ==> Definitely not a good idea.

Categories

Resources