What's new in C # 8.0 II: Interface default implementation

In C # 8.0, the interfaces for the introduction of a new feature is that you can specify the default implementation, easy to extend existing realization, also for Android and Swift's Api interoperability offers the possibility. Let us look at the characteristics of the specific rules and implementation.      

First, the main scenarios:

     Without damaging effects have been achieved, you can add new members. This solves the pain points Expanding on the already extensive use of third-party interface brings problems.

Second, the rules and restrictions:

1. Support members: methods, properties, indexers, and a variety of static members. Examples of fields not supported, examples of events, automatic properties, examples of construction and destructor

2. 支持修饰符:private, protected, internal, public, virtual, abstract, sealed, static, extern, and partial.

3. The default access level for the public, you can explicitly specify may not be specified.

4. In addition to the methods through the sealed body, and private modifications, with other members of the default method bodies are members virtural

The default interface implementation and interface inheritance belongs only to its sub-interface, but its implementation can not be inherited, so can only be called through the interface variables. Unless the implementation of the interface was achieved again.

6. The multi-level inheritance interfaces, default interface calls closest to achieving implementation. That is, "the level closest to the latest realization recently, the same level of new closer than overrided".

7. implement and cover member interfaces in the class without having to use new and override keywords, and implementation mechanisms of the interface is consistent, without any modification or operation.

Third, to achieve for example:

1. First define an interface IFlyable, code is as follows:

    public  interface IFlyable
    {
        // support const Constant 
        public  const  int the MAX_SPEED = 200 is ;
         const  int MIN_SPEED = 0 ; // default public, may be omitted 
        public  const  String SPEED_UOM = " m / S " ;
         Private  static  Readonly the Dictionary < String , String > nameDic;

        // supports static constructors, instance constructor does not support 
        static IFlyable ()
        {
            nameDic = new Dictionary<string, string>() { {nameof(MAX_SPEED),MAX_SPEED.ToString()}, {nameof(MIN_SPEED),MIN_SPEED.ToString()} };
        }

        // support indexers, but one of the variables can only be static variable. 
        String  the this [ String Key]
        {
            get
            {
                string tmp;

                if (nameDic.ContainsKey(key))
                {
                    tmp = nameDic[key];
                }
                else
                {
                    tmp = string.Empty;
                }

                return tmp;
            }
        }

        int Speed { get;}

        // default to public and virtual, so here is virtual and public non-essential 
        public  void the Initialize ()
        {
            var defaultSpeed = AverageSpeed();
            Initialize(defaultSpeed);

            WriteLine($"{nameof(IFlyable) + "." + nameof(Initialize)} at default {defaultSpeed} {SPEED_UOM}");
        }

        // private method with the members of the body is allowed 
        Private  int AverageSpeed ()
        {
            return (MAX_SPEED + MIN_SPEED) / 2;
        }

        void Initialize(int speed);

        // default to public and virtual, so here is virtual and public dispensable 
        void Fly ()
        {
            WriteLine($"{nameof(IFlyable) + "." + nameof(Fly)}");
        }
    }

2. Redefining a IAnimal interfaces:

    public  interface IAnimal
    {
        // default to public and virtual, can be explicitly pointed out that the members of the Virtual 
        void SayHello ()
        {            
            WriteLine($"{nameof(IAnimal) + "." + nameof(SayHello)}");
        }

        void Walk()
        {
            WriteLine($"{nameof(IAnimal) + "." + nameof(Walk)}");
        }
    }

3. Define a IFlyableAnimal interface inherited from the former two interfaces

    public  interface IFlyableAnimal: IAnimal, IFlyable
    {
        public new const int MAX_SPEED = 300;

        // rewrite IAnimal of SayHello, 
        void IAnimal.SayHello ()
        {
            WriteLine($"override {nameof(IFlyableAnimal) + "." + nameof(SayHello)} ");
        }

        // Because IFlyableAnimal interface extends IAnimal interfaces, add new keywords to hide inherited parent class SayHello, can not add, but there will be a warning. 
        public  new new  void SayHello ()
        {
            WriteLine($"new {nameof(IFlyableAnimal) + "." + nameof(SayHello)}");
        }
        
        // Because IFlyableAnimal interface extends IFlyable interface, the interface can not inherit the default implementation of the override keyword with 
        public  void Walk ()
        {
            WriteLine($"new {nameof(IFlyableAnimal) + "." + nameof(Walk)}");
        }
    }

4. Define a class Sparrow, to implement the interface IFlyableAnimal

    public class Sparrow : IFlyableAnimal
    {
        // implemented in IFlyable Speed interface 
        public  int Speed { GET ; Private  SET ;}

        // achieve IFlyable in the Initialize (int speed) Interface 
        public  void the Initialize ( int Speed)
        {
            this.Speed = speed;
            WriteLine($"{nameof(Sparrow) + "." + nameof(Initialize)} at {Speed} {IFlyable.SPEED_UOM}");
        }

        // implement and cover interface SayHello, without having to use new and override keywords, and implementation mechanisms of the interface is consistent, without any modification or operation. 
        public  Virtual  void SayHello ()
        {
            // Note the use IFlyableAnimal.SPEED_UOM, the class can only implement interfaces can not inherit the default implementation of the interface, but the interface can inherit the default parent interface to achieve 
            the WriteLine ($ " {NameOf (Sparrow) + " . " + NameOf (SayHello)} Speed IFlyableAnimal.SPEED_UOM {} {AT} " );
        }

    }

5. previously defined call

        static void Main(string[] args)
        {
            Sparrow bird = new Sparrow();
            bird.Initialize ( 98 ); // implemented Sparrow and covers the Initialize, so the class can be called directly 
            bird.SayHello (); // Sparrow and coverage achieved, so the class can be called directly
                             // bird.Fly ( ); Fly inaccessible because Bird did not realize it will not inherit the implementation of interfaces, so I do not have a Fly method.

            // IFlyableAnimal inherits the default IFlyable IAnimal and implementation, and calls the SayHello method Fly through the variable 
            IFlyableAnimal flyableAnimal = Bird;
            flyableAnimal.SayHello();
            flyableAnimal.Fly();

            // IFlyableAnimal inherited from IAnimal and IFlyable, while Sparrow class has inherited from the IFlyableAnimal, so you can call with IAnimal and IFlyable variable 
            IAnimal = Animal Bird;
            animal.SayHello();

            IFlyable flyable = bird;
            flyable.Initialize();
            flyable.Fly();

            Monster monster = new Monster();
            Alien IAlien = Monster;
             // alien.Fly (); // compiler can not distinguish between a 'IBird.Fly ()' or 'IInsect.Fly ()' 
        }

        //输出:
        //Sparrow.Initialize at 98 m/s
        //Sparrow.SayHello at 98 m/s
        //Sparrow.SayHello at 98 m/s
        //IFlyable.Fly
        //Sparrow.SayHello at 98 m/s
        //Sparrow.Initialize at 100 m/s
        //IFlyable.Initialize at default 100 m/s
        //IFlyable.Fly

 

Fourth, multi-level inheritance issues arising

       Because the interface can be multiple inheritance, so there will be similar in C ++ produce diamond inheritance problem. As shown below, IBird and IInsect inherit IFlyable, while IAlien and inherits IBird and IInsert two interfaces, and made a new implementation, then they form a diamond or diamond shapes. This time, to achieve a IAlien the Monster class, which will be unable to switch to distinguish Fly

 

 

code show as below:

    public interface IBird : IFlyable
    {
        void Fly()
        {
            WriteLine($"{nameof(IBird) + "." + nameof(Fly)}");
        }
    }

    public interface IInsect : IFlyable
    {
        void Fly()
        {
            WriteLine($"{nameof(IInsect) + "." + nameof(Fly)}");
        }
    }

    public interface IAlien : IBird, IInsect
    { 
    }

    public class Monster : IAlien
    {
        public int Speed { get; private set; } = 1000;

        public void Initialize(int speed)
        {
            this.Speed = speed;
        }
    }

The following call statement alien.Fly will lead to confusion, the compiler can not distinguish this Fly in the end is IBird.Fly () or IInsect.Fly ():

        static void Main(string[] args)
        {
            Monster monster = new Monster();
            Alien IAlien = Monster;
             // alien.Fly (); // compiler can not distinguish between a 'IBird.Fly ()' or 'IInsect.Fly ()' 
        }

 The solution to this problem is to either call the appropriate members through more specific interfaces (IBird or IInsect), either implement Monster Fly in class, and then be invoked through the class.

 

V. Summary

      The default interface to C # 8.0 is the realization of the extended features of the software provides a relatively large degree of flexibility, but also to introduce some rules that increase the cost of their master's. Here, I tried to find some of its rules to make a summary and show an example to be explained, and certainly inadequate pointed out, I hope you correct.

Guess you like

Origin www.cnblogs.com/markkang/p/12181666.html