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的混淆#_C#_Oop_Virtual Functions_Overriding_Sealed - Fatal编程技术网

C# 关于凌驾性规则C的混淆#

C# 关于凌驾性规则C的混淆#,c#,oop,virtual-functions,overriding,sealed,C#,Oop,Virtual Functions,Overriding,Sealed,我对方法重写和OOP原则的有效性有点困惑。 我知道一切关于密封,阴影,覆盖,虚拟等,但我遇到了一个场景,这只是困惑我。假设我有: class classA { public virtual void sayhello() { Console.WriteLine("hello I'm A"); } }; class classB :classA { public override void sayhello() {

我对方法重写和OOP原则的有效性有点困惑。 我知道一切关于密封,阴影,覆盖,虚拟等,但我遇到了一个场景,这只是困惑我。假设我有:

class classA
{

    public virtual void sayhello()

      {
        Console.WriteLine("hello I'm A");
    }

};

class classB :classA
{
    public override void sayhello()
    {
        Console.WriteLine("hello I'm B");
    }

};
class Program
{
    static void Main(string[] args)
    {

        classB a = new classB();
        a.sayhello();
    }
}
根据我到目前为止所研究的所有内容,可以在子类中使用override关键字覆盖声明为virtualabstract的方法(在抽象类中)。根据这一点,上面的代码工作得非常完美。 当我删除virtual关键字,然后尝试使用override关键字重写该方法时,编译器给出的错误如下:

无法重写继承的成员“Inheritance.classA.sayhello()”,因为它未标记为虚拟、抽象或重写

然后我从子类中删除了override关键字,并提供了如下实现:

class classB :classA
{
    public void sayhello()
    {
        Console.WriteLine("hello I'm B");
    }

};
在这种情况下,可以重写该方法。我可以重写这个方法,它不是虚拟的或抽象的。因此,我的问题是:

1.它没有违反OOP原则吗?因为我可以重写该方法,该方法在父级中未标记为virtual

2.为什么允许我以这种方式重写该方法?哪一个甚至没有标记为虚拟

3.从classA方法中删除virtual关键字,当我试图在classB中重写该方法时,它给了我一种在classA中密封方法的感觉。(正如我前面提到的编译器错误)。如果我删除了virtual,这样子类就不会覆盖它,那么为什么子类可以聪明地覆盖它,删除它的override关键字?这是唯一的情况吗,sealed关键字是为这种情况设计的吗

  • 它没有违反OOP原则吗?因为我可以重写该方法,该方法在父级中未标记为虚拟
  • 您没有覆盖父方法,您隐藏了父方法

    因此,您永远无法从子类对象访问父方法,因为它被子类
    方法sayhello()
    隐藏

    2.为什么允许我以这种方式重写该方法?哪一个甚至没有标记为虚拟


    因为您可以用子实现隐藏父方法。

    < P>我认为这是来自C++实现,使用SLIGEN()、

    虽然C++类似于java,但在某些情况下(这一个和值类型的存在)遵循C++方式。 这之后的推理是,由于您的代码从
    A
    变量调用方法
    sayhello
    ,程序员希望执行
    A.sayhello
    的逻辑。它不会违反OOP原则,因为您正在执行
    A.sayhello
    实现(因此它必须与
    A.sayhello
    契约匹配)

    与Java的区别不是OOP与非OOP,而是Java使用
    后期绑定
    (实际执行的方法在运行时根据
    a
    实际实例确定),而C#使用
    早期绑定
    (方法在编译时确定),除非该方法是虚拟的


    就我个人而言,我更喜欢后期绑定,虽然从面向对象的角度来看,C#方法是正确的,但我发现通常应该使用更专业的方法。

    好吧,最后它非常简单:

  • 重写虚拟方法时,具体方法将在运行时解析
  • 当使用
    new
    关键字(或完全忽略它)时,您正在编译时根据代码中可用的类型信息执行静态替换操作
    这是两件完全不同的事情。

    我想告诉你,你给隐藏的父子方法没有被覆盖。
    您可能还没有注意到的另一件事是看到警告,因为在警告部分中会清楚地提到

    警告“行号”
    “classB.sayhello”
    隐藏继承的成员
    “classA.sayhello”
    。使用新的 关键字,如果要隐藏

    你的问题,

    它没有违反OOP原则吗?因为我可以重写该方法,该方法在父级中未标记为虚拟

    不,它肯定没有违反OOP原则,因为您已经隐藏了基类方法

    为什么允许我以这种方式重写该方法?哪一个甚至没有标记为虚拟

    因为C#不仅支持重写,而且还支持方法隐藏,并且必须使用
    new
    关键字声明隐藏方法。有关更多信息,请阅读和

    这是唯一的情况,密封关键字是专为

    From
    sealed
    关键字用于防止派生类并否定虚拟成员的虚拟方面

    • 当应用于类时,sealed修饰符会阻止其他类从该类继承
    • 密封修饰符只能应用于重写基类中虚拟方法或属性的方法或属性。这可以防止进一步重写特定的虚拟方法或属性,但它永远无法停止
      方法隐藏
      。阅读了解更多信息

    您所做的是方法隐藏(正如其他人已经解释的)


    若你们真的想这样做,你们应该在方法定义中添加新的关键字,使警告消失,并作为一个文档。因此,其他查看您代码的开发人员知道您是故意这样做的。

    您执行了一个称为“方法隐藏”的概念,是的,但它不是违反了oop原则吗?比方说,classA不想让它的方法被隐藏?或者为什么我们要使用新的关键字进行阴影处理,是吗