澳门至尊网站-首页

您的位置:澳门至尊网站 > 免费资源 > Swift泛型Protocol对比C#泛型Interface

Swift泛型Protocol对比C#泛型Interface

2019-11-28 13:38

  本篇纯属抬杠之作,此前我们关系了斯威夫特的泛型Protocol使用associatedtype关键字,实际不是选用<Type>语法的泛型参数。那此中有如何好处吗?

  我就以此难题查找了部分答应,大意上涉及两点:

  <Type>语法对Protocol未有趣,Protocol仅需求定义三个虚幻的定义,具体的类型应该由完成的Class来名扬天下,比如:

ClassWithInt<Int>: NumberProtocol
ClassWithDouble<Double>: NumberProtocol

  associatedtype能够用来给Protocol中特定Func加多泛型节制,而不是限量整个Protocol

protocol GeneratorType {
    associatedtype Element
    public mutating func next() -> Self.Element?
}

  听起来仍有料定道理的,然后施行是核查事实的唯生龙活虎标准。上边大家因而代码实例来和C#开展相比较。首先拿出网络多被引用解释上述六个观点的Swift代码:

public protocol Automobile {
    associatedtype FuelType
    associatedtype ExhaustType
    func drive(fuel: FuelType) -> ExhaustType
}
public protocol Fuel {
    associatedtype ExhaustType
    func consume() -> ExhaustType
}
public protocol Exhaust {
    init()
    func emit()
}

public struct UnleadedGasoline<E: Exhaust>: Fuel {
    public func consume() -> E {
        print("...consuming unleaded gas...")
        return E()
    }
}
public struct CleanExhaust: Exhaust {
    public init() {}
    public func emit() {
        print("...this is some clean exhaust...")
    }
}
public class Car<F: Fuel,E: Exhaust>: Automobile where F.ExhaustType == E {
    public func drive(fuel: F) -> E {
        return fuel.consume()
    }
}

public class Car1<F: Fuel>: Automobile {
    public func drive(fuel: F) -> F.ExhaustType {
        return fuel.consume()
    }
}

  具体的选拔情况如下:

var car = Car<UnleadedGasoline<CleanExhaust>, CleanExhaust>()
car.drive(fuel: UnleadedGasoline<CleanExhaust>()).emit()

var fusion = Car1<UnleadedGasoline<CleanExhaust>>()
fusion.drive(fuel: UnleadedGasoline<CleanExhaust>()).emit()

  转换成C#代码的话,有三种思路,首先是把泛型参数放到Interface层面:

    public interface Automobile<FuelType, ExhaustType>
    {
        ExhaustType Drive(FuelType fuel);
    }
    public interface Fuel<ExhaustType>
    {
        ExhaustType consume();
    }
    public interface Exhaust 
    {
        void Emit();
    }

    public class UnleadedGasoline<Exhaust> : Fuel<Exhaust> where Exhaust : new()
    {
        public Exhaust consume()
        {
            Console.WriteLine("...consuming unleaded gas...");
            return new Exhaust();
        }
    }
    public class CleanExhaust : Exhaust
    {
        public void Emit()
        {
            Console.WriteLine("...this is some clean exhaust...");
        }
    }
    public class Car : Automobile<UnleadedGasoline<CleanExhaust>, CleanExhaust>
    {
        public CleanExhaust Drive(UnleadedGasoline<CleanExhaust> fuel)
        {
            return fuel.consume();
        }
    }

  还是能够效仿Swift对Automobile多做大器晚成层世袭进行打包:

    public interface Car1<T1> : Automobile<UnleadedGasoline<T1>, T1> where T1 : new()
    {

    }

    public class SimpleCar : Car1<CleanExhaust>
    {
        public CleanExhaust Drive(UnleadedGasoline<CleanExhaust> fuel)
        {
            return fuel.consume();
        }
    }

调用的时候未有怎么太大的差别:

  var gaso = new UnleadedGasoline<CleanExhaust>();
  var car = new Car();
  car.Drive(gaso).Emit();

  var simpleCar = new SimpleCar();
  simpleCar.Drive(gaso).Emit();

  和Swift比较不一致的是,大家在Interface就代入了泛型参数。不过出于大家无法直接实例化Interface,所以并不能够直接利用Automobile来压缩大器晚成层世袭关系。

  因为上述提到的应用associatedtype 的首先点理由见仁见智,这里不分高下。

  C#再有第三种思路,便是自身也把泛型约束下放到Func层级:

    public interface Automobile
    {
        ExhaustType Drive<FuelType,ExhaustType>(FuelType fuel) where ExhaustType : new();
    }
    public interface Fuel
    {
        ExhaustType consume<ExhaustType>() where ExhaustType : new();
    }

    public class UnleadedGasoline : Fuel
    {
        public Exhaust consume<Exhaust>() where Exhaust : new()
        {
            Console.WriteLine("...consuming unleaded gas...");
            return new Exhaust();
        }
    }

    public class Car2 : Automobile
    {
        public CleanExhaust Drive<UnleadedGasoline, CleanExhaust>(UnleadedGasoline fuel) where CleanExhaust : new()
        {
            return  (fuel as Fuel).consume<CleanExhaust>();
        }
    }

C#的接口并无法定义构造函数。强行模仿起来还真是有一些累啊。最后的选择也非常轻易:

    var fuel = new UnleadedGasoline();
    var car2 = new Car2();
    car2.Drive<UnleadedGasoline,CleanExhaust>(fuel).Emit();

  通篇比较下来,应该说Swift通过associatedtype 关键字和<Type>的混用,使得泛型的定义更为复杂也更加灵敏了。

  GitHub:

 

 

本文由澳门至尊网站发布于免费资源,转载请注明出处:Swift泛型Protocol对比C#泛型Interface

关键词: