Java: “Class Overloading”

2019-07-02 00:51发布

问题:

Okay, so let's say I have a class file called Orange, and then two separate class files called Color, and Fruit.

Inside Orange, there are some properties for color, size, ripeness etc. and the method setSize(int size).

Inside Fruit, there are some properties for name, type of fruit, whether or not it has seeds, where it was imported from etc. and then the methods setName(String name), eat(), wash() and give(Person person).

Inside Color there are some properties for name, RGB values, Hex values, Alpha values etc. and then the methods setName(), setAlpha(int alpha), setRGB(int r, int g, int b) and setHex(int hex).

Most of the above mentioned information is irrelevant, and solely there to assist you in understanding. The Orange Class file has an object in it called "Parent". What I need to know is, is it possible for the object "Parent" to be set to either a Fruit, or a Color? Later on in the main class file there comes a point where myOrange.Parent.setName("Bob") happens, and in both cases (whether Parent is a Fruit or a Color) it would be possible, because Fruit has a method called setName, and Color does as well.

Thanks

回答1:

Type Inheritance ("class overloading"?) represents an "is-a" relationship. The Orange is a Fruit. No additional variables are needed; inherited members are accessed via this.

Composition represents a "has-a" relationship. The Orange has a Color. A separate variable is declared when using this pattern, so this is clearly what is being used for Parent.

Thus Parent (a horribly named variable) is an instance of Color.



回答2:

It really depends on your use case. If the "Orange" class is representing the color orange, then it might make sense for it to inherit from the "Color" class. If it represents the fruit, then it might make sense to inherit from the "Fruit" class.

However, in neither case (at least with the information given) do I see a reason for the "Orange" class to have a "Parent" reference. It would make more sense (again, depending on your use case) for your "Orange" class to extend either Color or Fruit, as I said before.



回答3:

If by "parent" you mean "inherits from" then the answer is no. Orange can inherit from Fruit but not from Color. Inheritance must be an "is-a" relationship.

An Orange "is-a" Fruit, this is correct.

An Orange "is-a" Color mmmm does not sound right.



回答4:

What you may wish to do is make Color and Orange implement an interface named either "NameHolder" (if you want to expose both a getter and a setter) or "NameSetter" (if you just want to expose the setter).

Such as this (I'll use NameHolder as its the most common case):

interface NameHolder {
String getName();
void setName(String name);
}

class Color implements NameHolder {
// methods and fields, setter and getter implemented
}

class Fruit implements NameHolder {
// methods and fields, setter and getter implemented
}

In this fashion, Orange can hold its "parent" Object not as an Object (which has very little behavior) but as an instance of a NameHolder. This makes the line you've pointed out:

private NameHolder Parent;
myOrange.Parent.setName("Bob");

This line will compile without error (of course it will result in a NullPointerException at runtime if Parent is null). I should also point out that Java's coding guidelines recommend that fields be lowercase, so it should be per convention:

private NameHolder parent; 
myOrange.parent.setName("Bob");


回答5:

In a statically typed language like Java you cannot call a method on a variable, unless the type of the variable declares said method. The type of the variable restricts your access to the objects the variable points; it's like a window that lets you see only a part of the object behind it.

This is different from dynamically typed languages; there the variable type doesn't restrict access to the object. As long as the object has the method you are calling you're good to go.

So in Java you need to:

  1. create a new type that declares the setName method. The most flexible way to do this is by creating an interface. Then you
  2. declare to "implement" that interface in the classes that actually have a setName method, and
  3. use the interface you have created to declare the variable parent.

For example:

interface Nameable { void setName(String name); }

class Color implements Nameable {
    public void setName(String name) { }
    /* implement other Color methods */
}

class Fruit implements Nameable { 
    public void setName(String name) { } 
    /* implement other Fruit methods */ 
}

class Orange { Nameable parent; /* call parent.setName at some point */ }


回答6:

If Orange actually has a parent via inheritance, it should already have access to its member functions. It sounds like you're trying to get Orange to inherit from both Color and Fruit at the same time through a workaround because Java does not support multiple inheritance. This is probably not what you actually want to do. Your best bet is to set up a correct relationship which has already been hinted at.

public class Color{methods}
public class Fruit{methods}
public class Orange extends Fruit
{
  private Color orangeColor;
  //Other member variables and functions.
}

In this way, Orange is-a Fruit and has-a Color. If you want Orange to have the ability to BE either a Fruit OR a Color, you need to rethink what you want. It's always possible to have a Fruit with name="Orange" and a Color with name="Orange" without actually making them the same class.



回答7:

If you want to program it that way you could check before executing a method to see if "Parent" references an instance of Fruit or Color, and then execute the appropriate method call.