程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 編寫高質量代碼改善C#程序的157個建議——建議94:區別對待override和new,

編寫高質量代碼改善C#程序的157個建議——建議94:區別對待override和new,

編輯:C#入門知識

編寫高質量代碼改善C#程序的157個建議——建議94:區別對待override和new,


建議94:區別對待override和new

override和new使類型體系應為繼承而呈現出多態性。多態要求子類具有與基類同名的方法,override和new的作用就是:

  • 如果子類中的方法前面帶有new關鍵字,則該法被定義為獨立於基類的方法。
  • 如果子類中的方法前面帶有override關鍵字,則子類的對象將調用該方法。而不調用基類的方法。

我們來看一個繼承體系:

        public class Shape
        {
            public virtual void MethodVirtual()
            {
                Console.WriteLine("base MethodVirtual call");
            }

            public void Method()
            {
                Console.WriteLine("base Method call");
            }
        }

        class Circle : Shape
        {
            public override void MethodVirtual()
            {
                Console.WriteLine("circle override MethodVirtual");
            }
        }

        class Rectangle : Shape
        {

        }

        class Triangle : Shape
        {
            public new void MethodVirtual()
            {
                Console.WriteLine("triangle new MethodVirtual");
            }

            public new void Method()
            {
                Console.WriteLine("triangle new Method");
            }
        }

        class Diamond : Shape
        {
            public void MethodVirtual()
            {
                Console.WriteLine("Diamond default MethodVirtual");
            }

            public void Method()
            {
                Console.WriteLine("Diamond default Method");
            }
        }

Shape是所有子類的基類。

Circle類override父類的MethodVirtual,所以即使子類轉型為Shape,調用的還是子類方法:

            Shape s = new Circle();
            s.MethodVirtual();
            s.Method();

輸出為:

circle override MethodVirtual
base Method call

            Circle s = new Circle();
            s.MethodVirtual();
            s.Method();

輸出也為:

circle override MethodVirtual
base Method call

類型Rectangle沒有對基類做任何處理,所以無論是否轉型為Shape,調用的都是基類Shape的方法。
類型Triangle將基類Shape的virtual方法和非virtual方法都new了一般,所以第一種方法為:

            Shape s = new Triangle();
            s.MethodVirtual();
            s.Method();

因為子類應經new了父類的方法,故子類方法和基類方法完全沒有關系了,只要s被轉型為Shape,針對s調用搞得都是父類方法。

            Triangle triangle = new Triangle();
            triangle.MethodVirtual();
            triangle.Method();

調用的都是子類方法,輸出為:

triangle new MethodVirtual
triangle new Method


類型Diamond包含了兩個和基類一模一樣的方法,並且沒有額外的修飾符。這在編譯器中會提出警示。但是如果選擇忽略這些警示,程序還是一樣可以運行。

            Shape s=new Diamond();
            s.MethodVirtual();
            s.Method();

編譯器會默認new的效果,所以輸出和顯示設置為new時一樣。

輸出為:

base MethodVirtual call
base Method call

            Diamond s = new Diamond();
            s.MethodVirtual();
            s.Method();

輸出為:

Diamond default MethodVirtual
Diamond default Method
最後給一個綜合示例:

 static void Main(string[] args)
        {
            TestShape();
            TestDerive();
            TestDerive2();
        }

        private static void TestShape()
        {
            Console.WriteLine("TestShape\tStart");
            List<Shape> shapes = new List<Shape>();
            shapes.Add(new Circle());
            shapes.Add(new Rectangle());
            shapes.Add(new Triangle());
            shapes.Add(new Diamond());
            foreach (Shape s in shapes)
            {
                s.MethodVirtual();
                s.Method();
            }
            Console.WriteLine("TestShape\tEnd\n");
        }

        private static void TestDerive()
        {
            Console.WriteLine("TestDerive\tStart");
            Circle circle = new Circle();
            Rectangle rectangle = new Rectangle();
            Triangle triangel = new Triangle();
            Diamond diamond = new Diamond();
            circle.MethodVirtual();
            circle.Method();
            rectangle.MethodVirtual();
            rectangle.Method();
            triangel.MethodVirtual();
            triangel.Method();
            diamond.MethodVirtual();
            diamond.Method();
            Console.WriteLine("TestShape\tEnd\n");
        }

        private static void TestDerive2()
        {
            Console.WriteLine("TestDerive2\tStart");
            Circle circle = new Circle();
            PrintShape(circle);
            Rectangle rectangle = new Rectangle();
            PrintShape(rectangle);
            Triangle triangel = new Triangle();
            PrintShape(triangel);
            Diamond diamond = new Diamond();
            PrintShape(diamond);
            Console.WriteLine("TestDerive2\tEnd\n");
        }

        static void PrintShape(Shape sharpe)
        {
            sharpe.MethodVirtual();
            sharpe.Method();
        }

輸出為:

TestShape       Start
circle override MethodVirtual
base Method call
base MethodVirtual call
base Method call
base MethodVirtual call
base Method call
base MethodVirtual call
base Method call
TestShape       End

TestDerive      Start
circle override MethodVirtual
base Method call
base MethodVirtual call
base Method call
triangle new MethodVirtual
triangle new Method
Diamond default MethodVirtual
Diamond default Method
TestShape       End

TestDerive2     Start
circle override MethodVirtual
base Method call
base MethodVirtual call
base Method call
base MethodVirtual call
base Method call
base MethodVirtual call
base Method call
TestDerive2     End



 

轉自:《編寫高質量代碼改善C#程序的157個建議》陸敏技

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved