为什么从超类调用时调用子类的方法?

时间:2016-10-11 10:25:59

标签: java polymorphism override

我的代码如下所示:

public abstract class BaseClass{
  public void update() {
      //...
  }

  public void somethingHappenedSoCallUpdate() {
      update();
  }
}

public class ExtendingClass extends BaseClass{
  @Override
  public void update() {
      //...
  }
}

有一个ExtendingClass的实例,在某些时候调用方法somethingHappenedSoCallUpdate()。我希望该方法会调用BaseClass.update(),但调用ExtendingClass.update()。有人可以解释原因吗?

5 个答案:

答案 0 :(得分:1)

  

我希望该方法会调用BaseClass.update(),但会调用ExtendingClass.update()。有人可以解释原因吗?

因为这就是Java的定义方式。默认情况下,所有非private方法都是虚拟,这意味着当您重写方法时,在实例上调用的方法是实例的覆盖率最高的版本({{1在你的情况下,无论通过哪个类型引用进行方法调用。这是现代OOP语言中多态性的基础。

编译时类型引用告诉编译器代码是否可以访问该方法;对象的运行时类型告诉JVM覆盖要调用的方法。

我们举一个简单的例子:

ExtendingClass

答案 1 :(得分:0)

它是多态的:在运行时调用正确的方法,具体取决于它是动态绑定的对象的实际类型。

答案 2 :(得分:0)

您覆盖了方法,因此如果您仍希望运行抽象类中的代码,则需要在重写方法中隐式调用public class ExtendingClass extends BaseClass { @Override public void update() { super.update(); // Call the base method. } } 。所以......

public function searchCourier(){      
    if($this->processRequest){
        $err = false; 
        if(empty($this->requestData['lat'])){
            $this->responceData['message'] = "Please enter latitude";
            $err = true;
        }
        if(empty($this->requestData['long'])){
            $this->responceData['message'] = "Please enter longitude";
            $err = true;
        }
        if(!$err){
            $lat = $this->requestData['lat'];
            $long = $this->requestData['long'];
            $this->loadModel('UserDetail'); 
            $data = $this->UserDetail->query("SELECT id,courier_address,courier_lat,courier_long,( 3959 * acos( cos( radians( '$lat' ) ) * cos( radians( courier_lat ) ) * cos( radians( courier_long ) - radians( '$long' ) ) + sin( radians( '$lat' ) ) * sin( radians( courier_lat ) ) ) ) AS distance
            FROM user_details HAVING distance <= 5 ORDER BY distance LIMIT 0 , 20");
            $this->responceData['result'] = array();
            // check if has data returned
            if($data) {
                foreach($data as $val) {
                    // try to var_dump or print_r the $val
                    // print_r($val);
                    // if $val data is = array(
                    //    'UserDetails' => array(
                    //        "id" => "15",
                    //       "courier_address" => "Globallogic MIHAN SEZ Centre, MIHAN, Nagpur, Dahegaon, Maharashtra, India",
                    //        "courier_lat" => "21.0487625",
                    //        "courier_long" => "79.03471179999997"
                    //    ),
                    //    0 => array(
                    //        "distance" => 123.3
                    //    )
                    // );

                    // store data as array
                    $this->responceData['result'][] = array(
                        'user_details' => array(
                            "id"=> $val['UserDetails']['id'],
                            "courier_address"=> $val['UserDetails']['courier_address'],
                            "courier_lat"=> $val['UserDetails']['courier_lat'],
                            "courier_long"=> $val['UserDetails']['courier_long'],
                            "distance"=> $val[0]['distance']
                        )
                    );
                }
            }
            $this->responceData['status'] = 1;
            $this->responceData['message'] = "Success";
            $result = array(
              'responseData' => array(
                 'result' => $this->responceData['result']
              )
            );
            return json_encode($result);

        } else {
            $this->responceData['status'] = 0;
            $this->responceData['message'] = "Something Went Wrong.Please Try again";           
        }              
    }
}

希望有所帮助:)

答案 3 :(得分:0)

正如@hyde所说,Java方法是虚拟的,这意味着VM在运行时决定调用哪个方法。如果您在扩展somethingHappenedSoCallUpdate()的实例上调用BaseClass,则会调用BaseClass.somethingHappenedSoCallUpdate(),但由于ExtendingClass覆盖BaseClass.update(),因此会ExtendingClass.update()分组而不是BaseClass.update()

扩展方法时,你必须这样想: 无论何时扩展一个方法,你把它放在一个堆栈上,当你调用它时,Java会看到这个&#34; stack&#34;并调用最顶层的。这意味着如果你有一个BaseClass有一个update()方法,这个类可以通过X类扩展而不是覆盖update()方法,但是如果X + 1类有,那么Java将永远称之为X + 1的方法。

答案 4 :(得分:0)

因为你覆盖了子类中的更新,并且因为java方法是虚拟重写版本,所以调用它。

选项#1

覆盖更新,覆盖somethingHappenedSoCallUpdate()方法并使用super.update()代替update()

选项#2

在超类中将更新设为私有:

private void update()