首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

New关键字:为什么不调用派生方法?

基础概念

在面向对象编程中,new 关键字用于创建一个类的实例。当使用 new 关键字创建对象时,会调用基类的构造函数来初始化对象。然而,new 关键字并不会自动调用派生类(子类)的方法。

原因

  1. 构造函数调用顺序:在创建对象时,首先会调用基类的构造函数,然后才调用派生类的构造函数。如果在基类构造函数中调用了某个方法,而这个方法在派生类中被重写,那么调用的仍然是基类的方法,而不是派生类的方法。
  2. 静态绑定:在基类构造函数中调用的方法是通过静态绑定(编译时绑定)来确定的,而不是动态绑定(运行时绑定)。因此,即使派生类重写了该方法,调用的仍然是基类的版本。

解决方法

  1. 避免在基类构造函数中调用虚方法:如果基类构造函数中需要调用某个方法,并且这个方法可能在派生类中被重写,那么应该避免在基类构造函数中调用这个方法。可以将这个方法的调用移到派生类的构造函数中。
  2. 使用虚方法和动态绑定:确保在基类中将需要被派生类重写的方法声明为 virtual(虚方法),这样在运行时通过动态绑定来调用正确的方法版本。

示例代码

代码语言:txt
复制
using System;

public class BaseClass
{
    public BaseClass()
    {
        // 避免在基类构造函数中调用虚方法
        Console.WriteLine("BaseClass constructor");
    }

    public virtual void Display()
    {
        Console.WriteLine("BaseClass Display");
    }
}

public class DerivedClass : BaseClass
{
    public DerivedClass()
    {
        Console.WriteLine("DerivedClass constructor");
    }

    public override void Display()
    {
        Console.WriteLine("DerivedClass Display");
    }
}

public class Program
{
    public static void Main()
    {
        DerivedClass derived = new DerivedClass();
        derived.Display(); // 输出 "DerivedClass Display"
    }
}

参考链接

通过上述方法,可以确保在创建派生类对象时,正确调用派生类的方法。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

JavaScript 使用new关键字调用函数

使用new关键字调用函数 test.js 代码如下 function Person(name, age, obj) { var o = new Object(); o.name = name...; // this.sayName=function(){ alert(name); } console.log(this); } var friend=new...扩展 修改test.js代码 定义变量,存放匿名函数的地址,然后使用该变量来调用函数 var Person = function(name, age, obj) { var o = new Object...js函数名称(参数列表),会把对应的函数当做构造函数来使用,如果函数未定义返回值,默认的会返回通过构造函数(被调用函数)构造的对象实例;如果函数定义了返回值,则返回定义的返回值。...2、使用new js函数名称(参数列表)调用函数,函数中的 this 代表了新构造的对象实例。 3、可以直接通过定义变量,存放匿名函数的地址,然后使用该变量来调用函数

1.1K30

Js 使用new关键字调用函数和直接调用函数的区别

Person("Nicholas",29,"Software Engineer"); friend.sayName(); Person函数创建了一个对象,并以相应的属性和方法初始化该对象,然后又返回了这个对象...注意:构造函数在返回值的情况下,默认返回新对象实例。 看到这里,我就将上面的例子的new关键字去掉,发现和原来结果一样。...person.sayName(); 得出结论:使用new关键字是将函数当作构造函数调用,即为构造对象,若没有人为的重写调用构造函数时返回的值,那么返回的对象是由解析器自己生成的。...不使用new关键字调用函数,即为普通函数调用。 随即想到若是函数返回值是function型的呢?...),虽然new函数与直接调用函数产生的结果等同,但是是两个不同的过程,一个是构造对象、一个是函数调用

3.7K10
  • 关于在Spring 中方法内部调用自身方法事务 REQUIRE_NEW 生效的解释

    问题来自:Spring事务的传播行为中REQUIRES_NEW真的有效吗 这个是Spring 对拦截的实现有关。Spring 拦截实现的方法是动态生成一个代理类。...这种方式对 target.method() 方式的调用是可以拦截到的,对于类内调用 method() 方式则拦截不到。...}); dynamicProxy.a(); } } 执行结果为: invoke in proxy this is a this is b 从这可以看出你类内自行调用方法是不会被代理拦截到的...cglib 代理到 我们写一个测试方法来试下,在上面main 方法里最后加入测试代码: Enhancer enhancer = new Enhancer(); enhancer.setSuperclass...this is b Spring 针对这种情况通过 threadlocal 的方式暴露了当前类的代理,可以使用 AopContext.currentProxy(); 方式得到,使用获取到的代理类再调用方法就可以再次走事务的处理逻辑了

    1.5K30

    Java——this关键字调用本类属性、调用本类方法、表示当前对象)

    this是一个非常灵活的关键字,不会明确表示一个固定概念,比如int,它就是表示一个整型。...一个类中存在普通方法和构造方法,this调用本类方法时,对应的语法不同: 1)调用本类中的其他方法:this.方法() 一个类中可能存在很多方法,这些方法之间可以直接进行调用,但是不够标准,应用this....方法()调用,标准化风格。...2)调用本类其他构造方法:this() 一个类中可以有多个方法,且可以重载,并且构造方法在实例化对象时只能被调用一次。...在使用this()调用本类其他构造方法时,应该避免循环调用。 下面通过实例说明构造方法互调的意义所在。

    4.3K30

    为什么android API 中有很多对象的创建都是使用new关键字

    为什么android API 中有很多对象的创建都是使用new关键字?...比起工厂方法、builder模式,java 中不提倡直接使用构造方法创建对象(new),为什么android API 中还是有很多对象的创建都使用构造方法 ? 这只是个草稿 首先,谢邀。...,最后付出程序崩溃的代价,等等一系列“眼一花,手一滑”所导致的后果,或多或少给人们带来“使用new关键字直接创建对象不靠谱”的错觉,其实这种结论有些片面了,为什么呢?...静态工厂方法在创建参数化类型实例的时候,它们使代码变得更加简洁。 在调用参数化构造器时,即使类型参数很明显,也必须指明。...静态工厂方法,类如果不含共有的或者受保护的构造器,就不能子类化 因为子类需要在构造函数中隐式调用父类的无参构造函数或者显式调用有参构造函数,这和把类修饰成final所表达的效果一致。

    72430

    为什么推荐使用 stop、suspend 方法中断线程?

    我们知道像stop、suspend这几种中断或者阻塞线程的方法在较高java版本中已经被标记上了@Deprecated过期标签,那么为什么她们曾经登上了java的历史舞台而又渐渐的推出了舞台呢?...可以看到,当线程t1在获取到o1和o2两个锁开始执行,在还没有执行结束的时候,主线程调用了t1的stop方法中断了t1的执行,释放了t1线程获取到的所有锁,中断后t2获取到了o1和o2锁,开始执行直到结束...那么建议使用stop中断线程我们应该怎么去优雅的结束一个线程呢,我们可以存java开发者的注释中窥探到一种解决方案: Many uses of stop should be replaced by code...可以看到调用interrupt方法后并不会像stop那样暴力的中断线程,会等到当前运行的逻辑结束后再检查是否中断,非常的优雅。 注:运行举例代码可能不会打印出数字,这是因为t1线程运行到while(!...二、suspend的落幕 suspend方法的作用是挂起某个线程直到调用resume方法来恢复该线程,但是调用了suspend方法后并不会释放被挂起线程获取到的锁,正因如此就给suspend和resume

    80030

    为什么推荐使用 stop、suspend 方法中断线程?

    java版本中已经被标记上了@Deprecated过期标签,那么为什么她们曾经登上了java的历史舞台而又渐渐的推出了舞台呢?...,即强制线程停止执行,'Forces’似乎已经透漏出了stop方法的蛮狠无理。...那么建议使用stop中断线程我们应该怎么去优雅的结束一个线程呢,我们可以存java开发者的注释中窥探到一种解决方案: Many uses of stop should be replaced by code...可以看到调用interrupt方法后并不会像stop那样暴力的中断线程,会等到当前运行的逻辑结束后再检查是否中断,非常的优雅。 注:运行举例代码可能不会打印出数字,这是因为t1线程运行到while(!...二、suspend的落幕 suspend方法的作用是挂起某个线程直到调用resume方法来恢复该线程,但是调用了suspend方法后并不会释放被挂起线程获取到的锁,正因如此就给suspend和resume

    53820

    为什么start方法不能重复调用?而run方法却可以?

    run 方法 thread.run(); // 多次调用 run 方法 thread.run(); // 创建线程二 Thread thread2 = new Thread(new Runnable...为什么start不能被重复调用?...0,也就是是否为新建状态 NEW,如果不等于新建状态,那么就会抛出“IllegalThreadStateException”非法线程状态异常,这就是线程的 start 方法不能被重复调用的原因。...它的执行过程是:当线程调用了第一个 start 方法之后,线程的状态就会从新建状态 NEW,变为就绪状态 RUNNABLE,此时再次调用 start 方法,JVM 就会判断出当前的线程已经不等于新建状态...start 方法之所以不能被重复调用的原因是,线程的状态是不可逆的,Thread 在 start 的实现源码中做了判断,如果线程不是新建状态 NEW,则会抛出非法线程状态异常 IllegalThreadStateException

    71010

    为什么wait和notify方法要在同步块中调用

    (); } } 也就是说wait和notify方法要在基于同一个对象的同步块中使用,那么这是为什么呢?...为什么wait和notify方法要在同步块中调用? 我们先来发出一个灵魂拷问:什么时候才需要wait? 什么时候又需要notify?...我们假设我们要实现一个堵塞队列,如果不加同步块,我们的实现方法可能如下。...take,发现buffer.isEmpty 在消费者调用wait之前,由于cpu的调度,消费者线程被挂起,生产者调用add,然后notify 然后消费者调用wait (注意,由于错误的条件判断,导致wait...所以:wait和notify方法要在同步块中调用的根本原因是,这两个方法存在竞态条件。如果不加锁的话,那么wait被调用的时候可能wait的条件已经不满足了(如上述)。

    99920

    当类中的方法全部都是 static 关键字修饰时 ,它的构造方法最好作为 private 私有化,理由是方法全是 static, 不知道的人会去new对象去调用,需要调用构造方法。 但 static的

    当类中的方法全部都是 static 关键字修饰时 ,它的构造方法最好作为 private 私有化,理由是方法全是 static, 不知道的人会去new对象去调用,需要调用构造方法。...但 static的方法直接用类名调用就行!...this关键字的       如何理解呢?       ...D:调用不同     静态变量可以通过类名调用,也可以通过对象调用。     成员变量只能通过对象名调用。...static 被jvm调用,不用创建对象,直接类名访问。     void 被jvm调用,不需要给jvm返回值。     main 是一个通用的名称,虽然不是关键字,但是被jvm识别。

    1.1K20

    C#中的override和new关键字

    正确的结果是: 使用override关键字修饰的方法 这是一个虚方法 为什么使用关键字new修饰的方法调用的是父类的方法呢? 是不是很奇怪?...为什么使用override关键字的子类方法调用了,而使用new关键字的子类方法没有被调用。 首先看看override关键字:override方法为从基类继承的成员提供新的实现。...如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。 如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用方法,而不是调用基类方法。...可以从派生类中使用 base 关键字调用基类方法。 override、virtual 和 new 关键字还可以用于属性、索引器和事件中。 默认情况下,C# 方法为非虚方法。...然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法

    1.3K20

    解锁C++多态的魔力:灵活与高效的编码艺术(上)

    2.1.1 为什么需要基类指针或引用 在C++中,如果直接使用派生类对象,即使它重写了基类的虚函数,编译器仍然会使用静态绑定,即在编译时确定调用的函数版本。...2.2.1 虚函数的定义和基本特性 虚函数是在基类中用关键字 virtual 声明的成员函数。 虚函数可以在派生类中被重写(override),并在运行时决定调用派生类的重写方法。...virtual 关键字时,虽然也可以构成重写(因为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,建议这样使用。...2.4.1 为什么需要虚析构函数? 当基类指针指向派生类对象时,如果删除对象时基类的析构函数不是虚函数,那么调用的仅仅是基类的析构函数,而不会调用派生类的析构函数。...2.5.2 final 关键字 final 关键字用于两种情况: 防止类被继承:当你希望某个类再被继承时,可以将这个类标记为final。

    11710

    面向对象编程基础2(干货)

    注意:为屏蔽父类中的那个方法派生类中声明名称和类型、及函数名都要与父类的对应的方法相同,且声明这个方法的时候要用new关键字。 ? ?...多态--通过指向派生类的基类(统一)调用调用虚函数,会根据引用所指向派生类的实际类型,调用派生类中的同名重写函数,即为多态(个性张扬)。...调用顺序: ? ? ? 5.抽象方法和抽象类:解释一下,就是比虚方法更需虚的方法为什么呢,虚方法里面可以有实现的代码块,但是抽象方法里面是不允许有的。关键字abstract。...抽象类的抽象成员在派生类中需要使用override关键字实现。 6.密闭类和密闭方法关键字是sealed。 密闭类就是希望其他人通过继承来修改,密闭方法就是希望他人重写该方法。...一般基类方法希望被子类重写,就可以声明为virtual。如果是派生方法希望子类对其重写,同时是override重写,就可以使用sealed机制。

    1.1K20
    领券