-1

Consider this base class:

public class Cat {
  public void meow() {
    // meowing
  }
}

And for some reason, cats subclasses can't inherit from this Cat class, because they MUST inherit from another base class, and Java doesn't support multiple inheritance. Thus:

public class Cat1 extends BaseClass1 {

}

public class Cat2 extends BaseClass2 {

}

public class Cat3 extends BaseClass3 {

}

How can I dynamically augment instances of CatX classes to inherit that meow method from Cat class?

A pseudo code might be:

public cat1Instance = new Cat1();
Cat.augmentWithCatBehavior(cat1Instance);

Is there a way for me to achieve this?

Update: Composition is not what I want. For composition, I need to have an instance of Cat class in all of my Cat1 to CatN classes. I have to create a wrapper method in each class so that I can call that meow. It's a huge amount of boilerplate code. That's why I said augmenting dynamically.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • Composition over inheritance... – Luiggi Mendoza Jul 20 '18 at 14:21
  • @LuiggiMendoza, composition is not the solution here. I'll update – mohammad rostami siahgeli Jul 20 '18 at 14:21
  • 1
    Composition is a solution, not the only one. We need a better example of what you need to achieve to provide a more accurate solution. – Luiggi Mendoza Jul 20 '18 at 14:24
  • Is **Visitor** pattern possible to meet your needs? – Hearen Jul 20 '18 at 14:26
  • @LuiggiMendoza, as I explained, I don't want to act statically. I want to infuse behavior into my classes dynamically based on some logic. And I also don't want to undergo a huge amount of boilerplate code. – mohammad rostami siahgeli Jul 20 '18 at 14:26
  • 3
    Then you are using the wrong language. Plain and simple. – GhostCat Jul 20 '18 at 14:26
  • Yep, Java is not flexible in this case. But I'm developing for Android, thus not that much choices. In JavaScript it's super easy, of course because JavaScript is dynamic. – mohammad rostami siahgeli Jul 20 '18 at 14:28
  • The code for the different methods to execute must be written, so that cannot be avoided. Maybe you need to use some FP with `Consumer`s, `Function`s and such. – Luiggi Mendoza Jul 20 '18 at 14:28
  • 2
    Java 8 support default methods in interfaces. If you changed your `Cat` class to an interfaces, and the `meow()` method to a default method in your interfaces, each of your `CatN` classes could implement the `Cat` interface. This approximates multiple inheritance in Java. ref: https://dzone.com/articles/interface-default-methods-java – StvnBrkdll Jul 20 '18 at 14:28
  • Create a base class for all basex classes and extend cat – mallikarjun Jul 20 '18 at 14:29
  • “cats subclasses can't inherit from this Cat class, because they MUST inherit from another base class, and Java doesn't support multiple inheritance.” Your design is broken. Inheritance is not for sharing functionality, it’s for polymorphism. – VGR Jul 20 '18 at 14:31
  • 3
    From your last comment, I don't think SO is the issue here. I asked you to provide more info about your problem and the only thing you're doing is waiting for more answers. Seriously: if you provide more data or maybe an example of what you want to achieve, we can provide more info and help you better. Take into account that we don't know what you have, what kind of code you maintain nor such things... – Luiggi Mendoza Jul 20 '18 at 14:34
  • 3
    Whatever you say, but please **add an example of what you need**, just that :) – Luiggi Mendoza Jul 20 '18 at 14:38
  • I have rolled back your last edit. It is just flamebait and doesn't belong in a question, and it will only attract more discussion and downvotes. If you want to discuss Stack Overflow, please post a discussion question on https://meta.stackoverflow.com/ – Mark Rotteveel Jul 20 '18 at 14:45
  • @MarkRotteveel, it's OK, thank you so much for being helpful. – mohammad rostami siahgeli Jul 20 '18 at 14:46
  • 1
    Then they can move on to quality content. It's rude to downvote when they can't help. Simply leave. Let people manage their own affairs. What if I don't want feedback? – mohammad rostami siahgeli Jul 20 '18 at 19:37

4 Answers4

4

No, the structure of a Java class is fixed at compile time, and can only be inspected (using reflection) but not dynamically changed at runtime.

It is possible though to generate whole classes dynamically at runtime. Although that significantly defeats the purpose of using a statically compiled language, such as Java.

The other answer would be to look into AOP, which is supported in Java in some frameworks (for example in Spring AOP). Here the idea is to identify "crosscutting" concerns, and have the framework add the corresponding code in certain ways. A typical example of that would be to "annotate" methods to do "logging", and then the AOP framework just adds the code required to do some standardised logging.

StvnBrkdll
  • 3,924
  • 1
  • 24
  • 31
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Can you guide me in the way of AOP? – mohammad rostami siahgeli Jul 20 '18 at 14:27
  • 3
    @mohammadrostamisiahgeli This is not how this site works. We don't **train** you. This is a broad and wide topic. Seriously: it is your project, so *you* have to do the heavy lifting. First of all you have to research AOP, to then determine if it fits your need (maybe, just maybe), the answer from Faysal about default methods could do for you. – GhostCat Jul 20 '18 at 14:32
  • @GhostCat are you deliberately "saying" ASOP? Or do you mean to say "AOP"? What is "ASOP"? (trying to educate myself). – StvnBrkdll Jul 20 '18 at 14:33
  • 1
    @StvnBrkdll You are right, stupid (mental) typo. Thanks for the edit! – GhostCat Jul 20 '18 at 14:34
  • @GhostCat, I didn't ask to be trained. Thank you for guiding me to this level. I just asked for a simple clue. That would be nice if you could provide based on your experience. Otherwise, thanks for answering. – mohammad rostami siahgeli Jul 20 '18 at 14:35
  • 1
    As said, this isn't "simple" in the first place. We are talking about a serious, advanced thing here. Giving you enough information about that to do all the things you want to ... is the equivalent of training / teaching you for an hour or more. – GhostCat Jul 20 '18 at 14:36
  • @mohammadrostamisiahgeli AOP works like proxy methods: they have a defined behaviour that can be used for several objects like logging parameters, handling security, handling database transactionability, storing/retrieving data from cache, and on. – Luiggi Mendoza Jul 20 '18 at 14:38
3

Use an interface of Cat class instead of class and make your method default. Only for Java 8 and higher versions.

interface Cat {
   default void meow() {
    // meowing
   }
}
public class Cat1 extends BaseClass1 implements Cat {
    @Override public void meow() {}
}

And you can call the method of your child class as below:

Cat cat= new Cat1();
cat.meow();
malware
  • 393
  • 1
  • 3
  • 16
  • I keep forgetting about default methods. They aren't solving all problems, but maybe maybe they work here. Depends on context. – GhostCat Jul 20 '18 at 14:33
  • The thing with default methods is that they may need parameters or depend to other abstract methods of the interface. Just be careful when using them. – Luiggi Mendoza Jul 20 '18 at 14:36
  • @Faysal Mehmood I don't think your example uses composition, it looks like inheritance. see: https://stackoverflow.com/questions/2399544/difference-between-inheritance-and-composition – StvnBrkdll Jul 20 '18 at 14:40
  • Be aware of the limitations of this method. Interfaces can't have attributes, so in your default method, you won't be able to access attributes. You can only call other methods of the interface (that might be overriden down the hierarchy), and use arguments of the method. – fps Jul 20 '18 at 14:46
0

You cannot add methods to a class at runtime. You have two possible solutions:

  1. Use an interface to work around the need for multiple inheritance.
  2. Use an instance field and composition instead of inheritance.
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
0

You can't do that but you have two options open to explore

  1. Using interface, its always good to use inheritance to assign behaviour rather than using inheritance.

  2. Second option is using functional programming to return Consumer instance from the method which can be changed based on some logical condition.

Note: Functional programming enabled us in returning functions/behaviour which can help us a lot.