new 一个对象时要先构造父类,但是test()被覆盖了,调用的是子类的test()。package test;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;
public class TestTime { public static void main(String[] args) { //创建子类对象 new extendsBase(); new Base(); }
} class Base{ public Base(){ test(); } public void test(){ System.out.println("Base!"); } }
//继承Base,重写test方法 class extendsBase extends Base{ @Override public void test() { System.out.println("in children"); } public extendsBase() { System.out.println("in children ctr"); } }输出结果: in children in children ctr Base!
public class Problem { public static void Main(String[] args) { //创建子类对象 new extendsBase(); Console.ReadLine(); } }
class Base{ public Base(){ test(); } public virtual void test(){ Console.WriteLine("Base!"); } }
//继承Base,重写test方法 class extendsBase : Base{ public extendsBase():base() //注意此处显示的调用父类的构造函数,但输出结果仍然是:Why???? { } public override void test() { Console.WriteLine("Why????"); } }我们再看另一种情况,输出就是Base!:public class Problem { public static void Main(String[] args) { //创建子类对象 new extendsBase(); Console.ReadLine(); } }
class Base{ public Base(){ test(); } public void test(){ //此处我把virtual 关键词去掉了 Console.WriteLine("Base!"); } }
//继承Base,重写test方法 class extendsBase : Base{ public extendsBase():base() { } //由于父类存在一个test方法,那么在C#中函数前面不加new关键词的话,是编译不过去的。 //这是java虚函数和C#实体函数的区别 public new void test() { Console.WriteLine("Why????"); } } 其实你的代码,就等同于上面第一种情况的代码是一样的!不知道能不能给你一点思路
就是调用了覆盖了从父类继承来的指针,由RTTI来确保转型正确。
但是,如果像上面的代码,唯一能解释的就是,子类知道自己重写了父类的方法,主动的在运行时覆盖了父类方法
表中的指针,使父类的方法指针指向子类重写的方法,但是不确定这个是否是正确的。不知到背后的原理到底是什么?
或许是翻译的错!
http://developer.51cto.com/art/201009/225990_all.htm
这样回答太过于
你可以参考下面的文章。
http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.aspx
子类重写了test方法
继承了构造方法
然后你调用的时候是new的子类
所以是用的子类的test方法
因为继承了父类的构造方法
所以会执行test方法
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class TestTime { public static void main(String[] args) {
//创建子类对象
new extendsBase();
new Base();
}
}
class Base{
public Base(){
test();
}
public void test(){
System.out.println("Base!");
}
}
//继承Base,重写test方法
class extendsBase extends Base{
@Override
public void test() {
System.out.println("in children");
}
public extendsBase()
{
System.out.println("in children ctr");
}
}输出结果:
in children
in children ctr
Base!
在构造函数中调用虚函数不是个很好的习惯,如果extendsBase的test使用extendsBase的变量呢?变量是有的,但没有初始化呀。
public class Problem {
public static void Main(String[] args) {
//创建子类对象
new extendsBase();
Console.ReadLine();
}
}
class Base{
public Base(){
test();
}
public virtual void test(){
Console.WriteLine("Base!");
}
}
//继承Base,重写test方法
class extendsBase : Base{
public extendsBase():base() //注意此处显示的调用父类的构造函数,但输出结果仍然是:Why????
{
} public override void test() {
Console.WriteLine("Why????");
}
}我们再看另一种情况,输出就是Base!:public class Problem {
public static void Main(String[] args) {
//创建子类对象
new extendsBase();
Console.ReadLine();
}
}
class Base{
public Base(){
test();
}
public void test(){ //此处我把virtual 关键词去掉了
Console.WriteLine("Base!");
}
}
//继承Base,重写test方法
class extendsBase : Base{
public extendsBase():base()
{
}
//由于父类存在一个test方法,那么在C#中函数前面不加new关键词的话,是编译不过去的。
//这是java虚函数和C#实体函数的区别
public new void test() {
Console.WriteLine("Why????");
}
}
其实你的代码,就等同于上面第一种情况的代码是一样的!不知道能不能给你一点思路
你可以参考下面的文章。
http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.aspx
----------------------------------------------------------------------------------------------------------------------
我的意思是对象构造函数里最好不要有虚函数。因为构造期间,虚函数表是没有建立起来的,对象只能调用自己的函数,而不是虚函数表里的函数指针。
由于子类重写了父类的test方法,所以子类的方法表中存的是重写之后的test方法的地址,所以调用子类重写之后的test方法