Why can only higher-class methods be used if class-type conversion is performed in Java?

Asked 2 years ago, Updated 2 years ago, 166 views

The most incomprehensible part is that the parent class' method is only available when the type transformation is performed.

Although it can be understood that the ultimate purpose of transforming the shape is because it has the advantage of unifying all the parameters of the method.

In the context of "parent class = child class" I don't understand why only the methods of "parent class" are available.

Source: I was trying to answer a question from http://tryhelloworld.co.kr/courses/ Java-introduction/lessons/class-type conversion and I moved it here because I thought it would be good to run the code right away.

java class type-conversion

2022-09-22 21:53

3 Answers

What you asked is not limited to Java.

It requires an understanding of object-oriented design (object-oriented programming).

Conceptually, it's about abstraction and materialization From a compiler perspective, it is related to type inference.

The reason for abstraction in object-oriented design from an information processing perspective is to deal with the same information. The purpose is to deal with the same information in a common way. On the other hand, the reason for classification (creating subclasses) is to deal with information that is not identical. This means that each supports methods that can only be handled by subclasses.

First, when I understand conceptually, I'll give you an example of abstraction.

Gasoline cars, diesel cars, and electric cars are cars.

If you design this sentence, you can create a higher class of cars, a lower class of cars, like gasoline cars, diesel cars, electric cars.

// Example
public class Car {
    public void run();
}

class GasolinCar extends Car {
    public void BurnGasolin();
}

class DiselCar extends Car {
    public void BurnDisel();
}

class ElectorincCar extends Car {
    public void Charge();
}

So in the example above, the following statements are conceptually true.

But will the inverse of 1, 2, and 3 above be established?

It doesn't count.

In theory like this, when Carcar = new GasolineCar(), we can understand that this sentence is true. But the car is just a car, and it's not like you can tell the difference between a gasoline car, a diesel car and an electric car.

You understand so far, but don't you know that you still did the new GasolineCar() The question will remain.

This problem relates to the second problem, type inference from a compiler perspective.

Think about the following situations and think about whether you can deduce the type.

// case 1
public void case1(Car car) {
    car.run();
}
// // case 2
public void case2(Car car) {
    car.BurnGasolin();
}
// // case 3
public void case3(Car car) {
    car.BurnDisel();
}
// // case 4
public void case4(Car car) {
    car.Charge();
}

We can make hydrogen cars that inherit cars at any time, amphibious cars, and so on.

This means that at the time of compilation, you cannot predict what additional classes will occur (in the near or far future).

So we use Casting, which explicitly forces the compiler. I don't know about the compiler, but I'm letting the compiler know that the person who develops it knows so that when compiling, it doesn't

Car car = ...
GasolinCar gcar = (GasolinCar)gcar;

In the example above, we don't know what car is produced, but we can see that we try to change it to GasolineCar at the end. The compiler understands this much and moves on. The time when the above statement actually fails is when you run (runtime error). An error occurs when the car is not actually GasolineCar or something that inherits GasolineCar.

But what if we call GasolineCar's function without casting?

Car car = ...
car.BurnGasolin();

For the compiler, car does not have a Burn Gasoline function. As I said before, subclasses don't know what they have at this point (especially since we can't even think about future classes), so it's hard to be interested in what car is actually implemented.

I thought the above story would be easier than explaining it academically and algorithmically, so I solved it and explained it.

It's not easy to explain this in writing. It would be better to ask for advice from seniors and professors who can explain well around you.


2022-09-22 21:53

Let me give you an example.

There is a class called the Default Remote (BasicRemote). It has volume up/down and channel up/down functions. There is a class called Mute Remote (MuteRemote) that inherits the default remote control class. Additionally, it has a mute function.

Try executing the following code (press the Run button under the code).)

class CodeRunner{
    public static void main(String[] args){

        /* The remote actually contains MuteRemote.
         * But since it's a basic remote type, 
         * You are promised to use only the method in BasicRemote. */
        BasicRemote remote = new MuteRemote();

        //There is nothing wrong with calling volumeUp and volumeDown.
        remote.volumnUp();
        remote.volumnDown();

        /* The line below here causes an error.
         * Because remote is 
         * Because it was promised to use only the functionality of Basic Remote */
        //remote.mute();

        /* But the kernel in the remote is actually MuteRemote.
         * So you can put the kernel back in the MuteRemote and use it.*/
        MuteRemote muteRemote = (MuteRemote)remote;
        muteRemote.mute();
    }
}


class BasicRemote{
    public void volumnUp(){
        System.out.println("VolumnUp");
    }
    public void volumnDown(){
        System.out.println("VolumnDown");
    }
    public void channelUp(){
        System.out.println("ChannelUp");
    }
    public void channelDown(){
        System.out.println("ChannelDown");
    }   
}

class MuteRemote extends BasicRemote{
    public void mute(){
        System.out.println("Mute");
    }
}

I'm going to run it according to the code above Change BasicRemote=newMuteRemote(); to BasicRemote=newBasicRemote();. This will cause an error in the muteRemote.mute part. The essence is Basic Remote.


2022-09-22 21:53

Teacher Jung Doo-sik First of all, thank you for your answer.

To explain my question in more detail... From the above code

BasicRemote remote = new MuteRemote();

/* The line below this causes an error. * Because remote is * Because it was promised to use only the functionality of Basic Remote */ //remote.mute();

The actual kernel of the remote is MuteRemote The variables and methods that you can actually use are only those in the Basic Remote class It's about whether you promised to use it.

If this appointment is inevitable, /* But the kernel in the remote is actually MuteRemote. * So you can put the kernel back in the MuteRemote and use it.*/ MuteRemote muteRemote = (MuteRemote)remote; muteRemote.mute(); I wonder if you are forcing me to change the type like this.


2022-09-22 21:53

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.