Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法调用方法的最子类实现?_C#_Oop_Polymorphism - Fatal编程技术网

C# 有没有办法调用方法的最子类实现?

C# 有没有办法调用方法的最子类实现?,c#,oop,polymorphism,C#,Oop,Polymorphism,在我的游戏中,我在unity中制作了一个抽象的超类SpaceshipController,它包含一个实现方法protected void updatespaceshipmotation()。对于每一艘宇宙飞船,都有一个子类,其中一些子类中的方法被覆盖(protectednewvoidupdateplayermovement())。在超类中调用的方法使用了SpaceshipController的实现,我想知道在超类代码中调用该方法时,是否有方法在子类中调用该实现。您要问的是多态性。在您的场景中,您

在我的游戏中,我在unity中制作了一个抽象的超类
SpaceshipController
,它包含一个实现方法
protected void updatespaceshipmotation()
。对于每一艘宇宙飞船,都有一个子类,其中一些子类中的方法被覆盖(
protectednewvoidupdateplayermovement()
)。在超类中调用的方法使用了
SpaceshipController
的实现,我想知道在超类代码中调用该方法时,是否有方法在子类中调用该实现。

您要问的是多态性。在您的场景中,您可以通过在抽象类中提供默认实现(作为虚拟方法)来实现这一点,并且允许每个子类通过重写该方法来提供自己的实现

SpaceshipController
中,将
protected void updatespaceshipmotation()
更改为
protected virtual void updatespaceshipmotation()
。这告诉编译器对SpaceshipController和任何子类使用此默认实现

在子类中,将
受保护的新void updatePlayerMovement()
更改为
受保护的覆盖void updatePlayerMovement()
。这告诉编译器对这个特定的类使用这个修改过的实现

protected override void updatePlayerMovement(){
  base.updatePlayerMovement(); //you can also call the parent implementation first if you so choose.
  //now perform the actions specific to this sub class.

}

要回答这个问题:

不,不是你实施的方式

基类如何知道某个继承类的某个地方有一个覆盖其方法的方法,并且应该被调用


您必须使用
virtual
关键字正确继承(
override
)方法。为了显示差异,我还添加了一个
abstract
方法

public abstract class SpaceshipController 
{
    // already has an implementation but might be extended or overruled
    protected virtual void updateSpaceshipMovement()
    {
        // do something general
    }

    // does not have an implementation -> HAS to be implemented by subclass
    protected abstract void Something();
}
如果没有
abstract
方法,则可能根本不需要创建基类
abstract

现在在子类
override
中使用
virtual
方法。(并实现
摘要
部分。)

  • 意思是:
    该方法在基类中已经有一个实现,但仍可以覆盖或使用
    base.method()

  • 意思是:
    基类中没有实现=>必须由子类实现


如果所有子类都应该有自己的实现,并且根本不使用
base.updateSpaceshipMovement
,那么an可能会更好:

public interface ISpaceshipController
{
    void updateSpaceshipMovement();
}
一个
接口
可以解释为一个
抽象类
,它只包含
抽象
方法,但是以后的一个类可以实现多个接口,这使得它成为一个非常强大的工具

实施它,例如像

public class ExampleController : MonoBehaviour, ISpaceshipController
{
    // I have to implement this to fulfill the interface implementation
    public void updateSpaceshipMovement()
    {
        // do stuff
    }
} 

为什么您要使用
new
而不是使基方法
virtual
并在子类中重写?@babaknafas,因为我没有完全取消虚拟标识符的重写。
virtual
abstract
的不同之处在于:该方法在父类中已经有一个实现,但可以被重写使用
base.method
您已经说过“它已被覆盖”和“它是新的”。但“被推翻”和“新”是对立的。如果您不理解这个事实,那么停止编程,理解这个事实,然后以正确的理解重新开始。假设每个虚拟方法都声明了一个“槽”,每个重写都会在该槽中放置一个不同的方法,每个“新”都会生成一个新槽。现在你明白为什么“覆盖”和“新”是对立的了吗?“覆盖”表示“更改此插槽的值”,“新建”表示“保持旧插槽不变并创建新插槽”。如果你想在C#中成功编程,你需要了解它是如何工作的。在我的例子中,
spaceshipController
有很多已经实现的方法,所以它不能成为一个接口,但感谢你的详细回答。它解释得很好。我建议你清理一下
virtual
abstract
的定义。如前所述,“该方法在父类中已经有一个实现,但无论如何都可以被覆盖或使用base.method进行扩展”是否描述了基类或父类上的虚拟修饰符,这一点并不明显。
public class ExampleController : MonoBehaviour, ISpaceshipController
{
    // I have to implement this to fulfill the interface implementation
    public void updateSpaceshipMovement()
    {
        // do stuff
    }
}