为什么在子类对象调用方法时,“this”会指向父类,而不是子类?

huangapple go评论141阅读模式
英文:

Why does "this" refer to the parent class although a child class object calls the method?

问题

我认为我没有理解与继承或this语句有关的某些内容。
如果我执行父类的方法,该方法调用子类中实现的另一个函数,
尽管执行父类函数的对象是子类对象,但this指向的是父类函数。

例如:

父类方法

public BookingConfirmation templateMethod(BigDecimal value) {
        try {
            Boolean authenticate = this.authenticate();
            if (!authenticate)
                // TODO 编写自己的此情况的异常
                throw new UnsupportedOperationException("The account was not successfully authenticated!");

            System.out.println(this.getClass().toString());

            this.bookTransaction(new BigDecimal("100"));
            BookingConfirmation bookingConfirmation = this.createBookingConfirmation();
            return bookingConfirmation;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

protected BookingConfirmation createBookingConfirmation() {
        throw new UnsupportedOperationException("Not implemented yet");
    }

子类实现:

protected BookingConfirmation createBookingConfirmation(BigDecimal value) {
        try {
            String title = "Transfer from account " + this.id.toString() + " in the amount of " + value.toString() + " Euro";
            BookingConfirmation bookingConfirmation = new BookingConfirmation(title);

            return bookingConfirmation;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
英文:

I think I did not understand something related to Inheritance or the this statement.
If I execute a method of a parent class, which calls another function implemented in the child class,
this refers to the function of the parent class although the Object executing the parent's class function is a child class object.

For example:

Parent Class Methods

public BookingConfirmation templateMethod(BigDecimal value) {
        try {
            Boolean authenticate = this.authenticate();
            if (!authenticate)
                // TODO Write own Exception for this Case
                throw new UnsupportedOperationException("Das Konto wurde nicht erfolgreich authentifiziert!");

            System.out.println(this.getClass().toString());

            this.bookTransaction(new BigDecimal("100"));
            BookingConfirmation bookingConfirmation = this.createBookingConfirmation();
            return bookingConfirmation;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

protected BookingConfirmation createBookingConfirmation() {
        throw new UnsupportedOperationException("Not implemented yet");
    }

Child Class Implementation:

protected BookingConfirmation createBookingConfirmation(BigDecimal value) {
        try {
            String title = "Überweisung von Konto " + this.id.toString() + " in der Höhe von " + value.toString() + " Euro";
            BookingConfirmation bookingConfirmation = new BookingConfirmation(title);

            return bookingConfirmation;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

答案1

得分: 4

父类和子类中的方法具有不同的签名

  • 在父类中:createBookingConfirmation()
  • 在子类中:createBookingConfirmation(BigDecimal)

因此,该方法并没有被重写,而是被重载,因此

BookingConfirmation bookingConfirmation = this.createBookingConfirmation();

总是调用父类中的方法。修复的方法是给父类方法添加一个BigDecimal参数。

如果父类的方法被子类的方法重写,那么在运行时将会调用正确的子类方法。这个底层概念被称为动态分派


为了防止这些错误,我们应该始终使用@Override注解来注释那些意图覆盖超类方法的方法。如果被注解的方法在至少一个超类中不是一个有效的覆盖方法,编译器会生成一个错误。


关于问题措辞的一点说明:正如JCWasmx86在评论中指出的,不能将方法进行强制转换。可以进行强制转换的是变量。

英文:

The methods in parent and child have different signatures

  • In parent: createBookingConfirmation()
  • In child: createBookingConfirmation(BigDecimal)

Thus, the method is not overridden, but overloaded and as consequence

BookingConfirmation bookingConfirmation = this.createBookingConfirmation();

always calls the method in the parent class. A fix would be to give the parent class method a BigDecimal parameter.

If a method of a parent class is overridden by a method of the child class, the correct child-class method will be called at runtime. The underlying concept is known as dynamic dispatch.


To prevent these kinds of mishaps, we should always annotate methods that are meant to override methods of supertypes with @Override. The compiler will generate a compiler error if the annotated method does not override a method in at least one supertype.


A remark on the wording of the question: As was pointed out by JCWasmx86 in the comments, one cannot cast a method. What one can cast is a variable.

huangapple
  • 本文由 发表于 2020年8月29日 17:05:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/63645271.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定