Why can a super class be initialized as a child cl

2020-06-16 02:27发布

问题:

In a nutshell, how and why is this possible:

Object obj=new MyClass();

Object is the superclass of all objects, therefore MyClass is a child class of Object. In general, in Java, Why is it possible to use the constructor of a child class in the parent class?


I understand how it could go the other way around, since the child has all the variables/methods of the parent class, so when you initialize them you are just initializing the variables specified in the parent constructor, that exist by definition in the child. The problem is, when you go the other way around, it is not necessarily true. A child can have variables the parent doesn't, so how is it possible to use the child constructor with the parent, when the parent does not even have the variables in the first place?


What uses does this feature have in development? I would think that if you want an instance of class B, you would declare it as B thing=new B(), and not A thing=new B(). This is probably my inexperience talking, so I would appreciate enlightenment on why and how a parent class can be initialized as one of its children.

回答1:

Why is it possible to use the constructor of a child class in the parent class?

This is not correct. When you do

Object obj = new MyClass();

Object obj; declares a reference of the type Object and new MyClass(); returns a reference to the object it created.

So, you are instantiating a MyClass and assigning the reference to the object created to a reference of the type Object, and this is possible because MyClass is an Object.

As you say,

A child can have variables the parent doesn't

That's called extending the parent functionality (inheritance).

For your second question think about the classic Animal example: Suppose you create a Animal class and you create a method makeSound() on it.

Now you create two subclasses of Animal, Dog and Cat, that overrides the makeSound()method of Animal (a Dog barks and a Cat meows).

Imagine that you represent a room full of Animals (Dogs and Cats) using a List, and you want to make all of them makeSound(). Your list will be declared as List<Animal> because you don't know the kind of Animals that you will store.

And then you iterate over the List to call makeSound() for each Animal. It doesn't matter if the Animal is a Dogor a Cat, it will make it's sound.

And then imagine you want to add Birds to the List. Easy, isn't it?



回答2:

You are thinking in terms of C++ semantics, but this is Java. In Java, all non-primitive type variables are references, not instances.

In C++, when you say

Object obj;

you allocate a new Object instance on stack or in static memory.

When you say

Object obj = new MyObject;

you invoke a constructor of Object class that takes MyObject pointer (or may be something else that MyObject can be converted to).

In Java,

Object obj;

does not create any instances of Object. It simply creates a variable that can have a reference to an Object instance, but at the moment does not refer to any. It is initialized to null.

Object obj = new MyObject();

allocates an instance of MyObject. It does not allocate a new instance of Object. It simply sets the variable to refer to the new instance. In C++ terms this is much more similar to

Object *obj = new MyObject();

So we're not constructing a parent instance from child instance. We're changing a value the variable is set to, from null to a new child instance.



回答3:

First, you must get a clear understanding of things. Your example expression: Object obj = new MyClass(); is actually a compound of two elementary operations.

The first one is creating an instance of MyClass: new MyClass(). The new keyword is basically the only way of actually obtaining an instance of a class (lets ignore runtime reflection to keep this simple), and you are literally naming what you want to create (MyClass) here by its constructor. There is no way to create anything other than what you literally named with the new keyword. The result of new is (implicitly) an instance of MyClass, but the explicit result of a new X is a reference of type X (the reference referring to the newly created instance).

Now the second operation is assigning the reference to your (new) MyObject to another reference of type Object. And this is valid because MyObject is an Object (due to inheritance).

Why would you need this?

This is an essential feature to actually make use of polymorphism. The ability to refer to any child class as its superclass is what makes polymorphism so powerful. You basically will use it everywhere where there is an aspect common to two classes, but there are also differences.

A real world example would be graphical user interfaces. There are buttons, lists, tables and panels in a window, which are all user interface elements, but each does a different thing. To present them neatly organized in a window, these elements are often nested into panels, more abstractly said into containers. Now a container doesn't care what kind of elements go into it, as long as they are components. But to handle them properly a container does need some basic information about these components, mostly how much space they occupy and how to actually draw them. So this is modelled as something like:

public abstract class Component {
    public int getWidth() { ... }

    public int getHeight() { ... }

    public void paint(Graphics g) { ... }
}

public class Container extends Component {
    public void add(Component child) { ... }

    public void paint(Graphics g) {
        for (Component child : children) {
            child.paint(g);
        }
    }
}

Thats almost straight lifted out of the JDK, the point is, if you needed to refer to each Component as its concrete type, it would be impractical to build a Container, it would need extra code for each Component you decide to make (e.g. there would be an addButton, addTable and so on). So instead, Container just works with reference to Component. No matter what Component is created (e.g. Button, CheckBox, RadioButton etc.), since Container just relies on them to all be Component's, it can handle them.



回答4:

Every class in Java is descended from Object. So MyClass is an Object, by definition, but a more specialized version of it. Think of it like this: every living creature is an Animal. A Cat is a special kind of animal; a specific type. Since the Cat is an Animal, you can still just call it an Animal:

Animal a = new Cat();

But doing so, with a, you can't do anything specific to a Cat, like meow() or purr(), but you can call methods which are valid for all Animals, such as breathe().

HTH



回答5:

class myMobile{
  public void call{
     System.out.println("Mobile");
      }
  }
    public class mainClass{
        public static void main(){
            Object o=new myMobile();
                //here we can call methods which are common to all 
                                     // objects not specific to 
                                                   // myMobile object
           }
  }


回答6:

Because a MyClass is a Object. Note that java is special because Object is the superclass of every other class type (there is no equivalent in C++).

A more interesting example would be if you had a class or interface and one or more subclasses. This comes up all the time in OOD. Consider for example java's jdbc API: a common set of interfaces to connect and query a database that can be implemented by different concrete classes. You only need to code to the API and then at runtime use the implementation for your DB of choice.



回答7:

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.

i.e. every Java class is an Object. This is why.

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

The Object class, defined in the java.lang package, defines and implements behavior common to all classes—including the ones that you write. In the Java platform, many classes derive directly from Object, other classes derive from some of those classes, and so on, forming a hierarchy of classes.



回答8:

You have two separate things here:

  • The construction of a new instance
  • The assignment of that instance to a variable

Since your instance of MyClass is also an instance of Object, this works well.

Consider the following, generic situation:

class A extends B implements C,D {
}

As your A is a B and also a C and a D and an Object, once you created an instance, you can (directly or indirectly) assign it to variables of all those types:

A a = new A();
B b = a;
C c = a;
D d = a;
Object o = a;

Your view on the fields or methods is limited by the type of the variable (i.E. as variable of type C, you only see the methods declared by C). Nevertheless, your instance is always of the type you instanciated using the constructor, regardless of the variable type.