Loading

C# abstract 与 virtual

 

---------------------------------------------------------------------------------------------------The knowledge comes from Professional C# 7.0 and .NET Core 2.0

 

Abstract Classes and Methods

C# allows both classes and methods to be declared as abstract. An abstract class cannot be instantiated,whereas an abstract method does not have an implementation and must be overridden in any on abstractderived class. Obviously, an abstract method is automatically virtual (although you don’t need to supplythe virtual keyword, and doing so results in a syntax error). If any class contains any abstract methods,that class is also abstract and must be declared as such.Let’s change the Shape class to be abstract. With this it is necessary to derive from this class. The new method Resize is declared abstract, and thus it can’t have any implementation in the Shape class (code file VirtualMethods/Shape.cs):

public abstract class Shape
{
   public abstract void Resize(int width, int height); // abstract method
}

When deriving a type from the abstract base class, it is necessary to implement all abstract members. Otherwise, the compiler complains:

public class Ellipse : Shape
{
   public override void Resize(int width, int height)
   {
      Size.Width = width;
      Size.Height = height;
   }
}

Of course, the implementation could also look like the following example. Throwing an exception of type NotImplementationException is also an implementation, just not the implementation that was meant to be and usually just a temporary implementation during development:

public override void Resize(int width, int height)
{
   throw new NotImplementedException();
}

NOTE
Exceptions are explained in detail in Chapter 14, “Errors and Exceptions.” Using the abstract Shape class and the derived Ellipse class, you can declare a variable of a Shape. You cannot instantiate it, but you can instantiate an Ellipse and assign it to the Shape variable :

Shape s1 = new Ellipse();
DrawShape(s1);

 

Virtual Methods

By declaring a base class method as virtual, you allow the method to be overridden in any derived classes:

public class Shape
{
    public virtual void Draw() => Console.WriteLine($"Shape with {Position} and {Size}");
}

In case the implementation is a one-liner, expression bodied methods (using the lambda operator) can also be used with the virtual keyword. This syntax can be used independent of the modifiers applied:

public class Shape
{
     public virtual void Draw() =>  Console.WriteLine($"Shape with {Position} and {Size}");
}

It is also permitted to declare a property as virtual. For a virtual or overridden property, the syntax is the same as for a non-virtual property, with the exception of the keyword virtual, which is added to the definition. The syntax looks like this:

public virtual Size Size { get; set; }

Of course, it is also possible to use the full property syntax for virtual properties. The following code snippet makes use of C# 7 expression-bodied property accessors:

private Size _size;
public virtual Size Size
{
  get => _size;
  set => _size = value;
}

For simplicity, the following discussion focuses mainly on methods, but it applies equally well to properties.
The concepts behind virtual functions in C# are identical to standard OOP concepts. You can override a virtual function in a derived class; when the method is called, the appropriate method for the type of object is invoked. In C#, functions are not virtual by default but (aside from constructors) can be explicitly declared as virtual. This follows the C++ methodology: For performance reasons, functions are not virtual unless indicated. In Java, by contrast, all functions are virtual. C# differs from C++ syntax,though, because it requires you to declare when a derived class’s function overrides another function,using the override keyword (code file VirtualMethods/ConcreteShapes.cs):

public class Rectangle : Shape
{
   public override void Draw() => Console.WriteLine($"Rectangle with {Position} and {Size}");
}

 


This syntax for method overriding removes potential runtime bugs that can easily occur in C++, when a method signature in a derived class unintentionally differs slightly from the base version, resulting in the method failing to override the base version. In C#, this is picked up as a compile-time error because the compiler would see a function marked as override but would not see a base method for it to override.The Size and Position types override the ToString method. This method is declared as virtual in the base class Object:

public class Position
{
   public int X { get; set; }
   public int Y { get; set; }
   public override string ToString() => $"X: {X}, Y: {Y}";
}
public class Size
{
   public int Width { get; set; }
   public int Height { get; set; }
   public override string ToString() => $"Width: {Width}, Height: {Height}";
}

 

NOTE
The members of the base class Object are explained in Chapter 3.
NOTE
When overriding methods of the base class, the signature (all parameter types and the method name) and the return type must match exactly. If this is not the case then you can create a new member that does not override the base member.
Within the Main method, a rectangle named r is instantiated, its properties initialized, and the method Draw invoked (code file VirtualMethods/Program.cs):

var r = new Rectangle();
r.Position.X = 33;
r.Position.Y = 22;
r.Size.Width = 200;
r.Size.Height = 100;
r.Draw();

 

Run the program to see the output of the Draw method:
Rectangle with X: 33, Y: 22 and Width: 200, Height: 100
Neither member fields nor static functions can be declared as virtual. The concept simply wouldn’t make sense for any class member other than an instance function member.

 

posted @ 2021-01-26 15:04  代码是一种反思  阅读(65)  评论(0)    收藏  举报