views:

105

answers:

5

So I think I have a pretty basic question. Say there's an open source Java program called com.cow.moo that you include in your project com.bee.buzz.

moo has a bunch of great classes, most of which you don't want to touch, but there are a couple you do. Now at this point, the best thing to do would be to extend the classes you want to modify, right? (I know there's been a lot said of extends vs. implements, but none of these classes are interfaces, so that's kind of out of the question.)

My question is, say this is the class in moo:

package com.cow.moo;
public class Milk {
    private float currentMilk;
    public int getMilk() { /* Stuff */ }
    public float convertToGallons (float liquid) { /* More Stuff */ }
}

Now, say I want to just use getMilk in my new class that extends Milk. However, getMilk in Milk relies on private variables (like currentMilk) and other functions I won't be including (like convertToGallons.) Will I have to include those other variables and functions if I want my new function to work correctly? I don't want to heavily modify the function, just add a little bit to it. What's the best way to do this?

Tips in general in building off a larger project would be useful, too. I figure it won't even take five seconds for some of the Java experts here to come up with an answer. Thanks for your time.

+1  A: 

I think in this case better solution will be polymorphism (static polymorphism), or you can use reflection (do not use this way) to reach to the private variable.

jitm
A: 

You can extend the class and access instance variables throught method accessors (getters & setters) if they are public.

You can use AOP (Aspect Oriented Programming) to change your moo classes at runtime without changing its sources.

Consider too read some Composition vs. Inheritance topics.

Hope this will help you.

SourceRebels
Thanks, I'll take a look at those.
Andrex
+6  A: 

The general recommendation is to favor composition over inheritance.

Say, you have an interface and an existing implementation that mostly fits you needs, like

public interface MilkProvider { public float getMilk(); }
public class Milk implements MilkProvider { // same as you example }

and need another custom implementation, you could code it like that:

public class MyMilk implements MilkProvider {
  private MilkProvider milk; 

  public MyMilk(int someValue) {
    milk = new Milk(someValue);  // unfortunatly we can't get rid of a depencency
                                 // to the concrete class because we need to create
                                 // something. An existing factory could help, but
                                 // but usually there's none implemented.
  }

  public float getMilk() {
    float result = milk.getMilk();
    // do somethink with the result
    return float;
  }
}
Andreas_D
I did say that none of them are interfaces, but are you suggesting I make an interface for the class I want to use, and then make my class and implement from that? I'd really like to not mess with the classes I imported.I did mention the extends vs. implements in the original question.
Andrex
No, I added the fictive interface just for demonstration purposes. You can remove that MilkProvider interface from the class declarations and change `private MilkProvider milk;` to `private Milk milk;`. But if you design something new, then you should create interfaces.
Andreas_D
A: 

You won't be able to use private class members unless you use Java reflection which will be kind of ugly. If I were you (and the changes are not too heavy, in which case I'd fork the original project), I'd look at modifying the code at runtime or statically using aspect weaving (aspect oriented programming). AspectJ may look as if it had a sharp learning curve, but it's a great tool to have in your toolbox and perfectly matches your needs here.

Dawid Weiss
+1  A: 

Now, say I want to just use getMilk in my new class that extends Milk. However, getMilk in Milk relies on private variables (like currentMilk) and other functions I won't be including (like convertToGallons.) Will I have to include those other variables and functions if I want my new function to work correctly?

You won't have to include the public functions and variables. The core concept of inheritance is that, as a subclass, you get all of your parent class's public (and protected) members included in your subclass for free. So your subclass (let's say HoneyMilk) can call convertToGallons right from the get-go.

Overriding getMilk in this case is a lot trickier, since it relies on a private variable (which your subclass cannot access). My advice is to shift your mindset from treating the class as a "white box" to a "black box". What I mean by that is that you should implement your overridden version of getMilk as if you weren't actually able to see Milk's source code. While it may seem like a roundabout solution (I mean, why can't I just go tweak this line here?!), this will force you to implement your subclass using only what the parent class exposes publicly. It also heavily emphasizes the importance of abstraction, which is absolutely crucial to utilize when developing large-scale projects.

htw
This is pretty much the answer I was looking for, thank you. Aspect-Oriented Programming and reflection are a bit out of reach for what I want to accomplish here. Thanks again.
Andrex