域名自动更新中,sem seo新手好做吗,做旅游销售网站平台ppt,苏宁易购电子商务网站建设目标软件工程的一个主要部分就是构建组件#xff0c;构建的组件不仅需要具有明确的定义和统一的接口#xff0c;同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。 在C#和Java中#xff0c;可以使用泛型构建的组件不仅需要具有明确的定义和统一的接口同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。 在C#和Java中可以使用泛型来创建可复用的组件并且组件可支持多种数据类型。这样便可以让用户根据自己的数据类型来使用组件。 泛型的简单案例 首先用泛型写一个Hello Worldidentity函数。identity函数将会返回我们传入的数据。你可以认为它是个echo命令。不用泛型我们也不用给identity函数指定类型 function identity(arg: number): number {return arg;
} 或者我们可以给identity函数指定any类型 function identity(arg: any): any {return arg;
} 虽然使用any类型的时候可以接收任何类型的arg参数但是实际上已经失去函数返回值类型的信息。假如我们传入一个number我们只知道返回任何类型的值都是可以的。 所以我们需要一直方式来捕捉参数的类型也可以用它来表示返回值的类型。这里使用的是类型变量一种特殊的变量代表的是类型而非值。 function identityT(arg: T): T {return arg;
} 现在我们已经为identity函数添加了类型变量T。T允许捕获用户提供的参数类型(如number)以便我们稍后可以使用该类型。然后我们再次用T作为返回值的类型。现在我们可以看到同一类型被用来作为参数类型和返回值类型。 我们称这个版本的identity函数为泛型它可用于多种类型。与使用any类型不同它和第一个identity函数(使用number作为参数类型和返回值类型)一样精准(它不会失去任何信息)。 一旦我们定义了泛型函数有两种方法可以使用。第一种就是传入所有的参数包括类型参数 var output identitystring(myString); // output的类型将会是 string 在这里我们明确的将T指定为string作为函数中传入的参数使用包裹该参数而非()。 第二种是最常见的。我们使用/类型推断/我们希望编译器根据传入的参数自动为T指定类型。 var output identity(myString); // output的类型将会是 string 注意我们并未显示的给尖括号内传入类型编译器检查myString然后将T设置为它的类型。虽然类型推断是个很实用的工具也能够使代码简短易读但你还是需要跟前面的例子一样明确的传递类型参数因为可能会存在复杂的函数使得编译器未能正确的进行类型推断。 使用泛型 当你开始使用泛型你可能会注意到当你创建一个类似identity的泛型函数编译器会强制要求你在函数中正确的使用这些通用类型参数。也就是说你真的把这些参数视为可以是任何类型的。 再看看之前的identity函数 function identityT(arg: T): T {return arg;
} 想要每次调用的时候在控制台打印出arg参数的length。我们可以尝试这么写 function loggingIdentityT(arg: T): T {console.log(arg.length); // 错误: T 不存在 .lengthreturn arg;
} 当我们这么做的时候编译器会抛出一个错误提示我们使用arg的.length属性但是没有地方指定过arg的.length属性。之前我们说类型变量代表了所有类型所以可能使用这个函数的时候会传入一个number类型的值而number是没.length属性的。实际上我们想让这个函数接受的参数是个T类型的数组而非直接T。当传入的是数组length属性便是可用的了。我们可以像创建其他数组类型一样 function loggingIdentityT(arg: T[]): T[] {console.log(arg.length); // 数组中存在 .length所以没报错return arg;
} 你可以这样理解loggingIdentity函数loggingIdentity泛型函数参数类型是T,参数arg是个类型为T的数组返回的也是个类型为T的数组。如果我们传入一个都是数字的数组那么我们也会得到一个都是数字的数组因为这时候T类型已经绑定为number了。这使得我们可以使用类型变量T作为我们使用的类型的一部分而非全部类型这也更具灵活性。 我们可以通过这种方式写个例子 function loggingIdentityT(arg: ArrayT): ArrayT {console.log(arg.length); // 数组中存在 .length所以没报错return arg;
} 泛型类型 在前面例子中我们创建了通用的identity函数可以使用于不同的类型。现在我们将探讨函数类型及如何创建泛型接口。 泛型函数的类型与非泛型函数一样只是最前面放上一个类型参数类似与声明函数 function identityT(arg: T): T {return arg;
}var myIdentity: T(arg: T)T identity; 我们也可以给类型中的泛型类型参数指定不同的名称只要类型变量的数量和其使用方式都能对应的上。 function identityT(arg: T): T {return arg;
}var myIdentity: U(arg: U)U identity; 我们也可以使用对象字面量的签名调用来写泛型类型: function identityT(arg: T): T {return arg;
}var myIdentity: {T(arg: T): T} identity; 下面开始写第一个泛型接口。用上个例子中的对象字面量来写接口 interface GenericIdentityFnT {(arg: T): T;
}function identityT(arg: T): T {return arg;
}var myIdentity: GenericIdentityFnnumber identity;
var num myIdentity(10); // 正确因为类型是number
var str myIdentity(10) // 错误参数类型不是number 注意我们的例子稍微有些改变。我们把非泛型函数签名作为泛型类型的一部分而不是去描述泛型函数。当我们使用GenericIdentityFn我们还需要指定对应的类型参数(这里是number)有效的锁定在底层签名调用时会用到的类型。理解何时将类型参数直接放到签名调用和何时将它放到接口上将有助于描述哪部分类型属于泛型。 除了泛型接口我们还可以创建泛型类。请注意不可能创建泛型枚举和模块。 泛型类 泛型类和泛型接口相似。泛型类在类名后面使用尖括号包含泛型类型参数列表。 class GenericNumberT {zeroValue: T;add: (x: T, y: T) T;
}var myGenericNumber new GenericNumbernumber();
myGenericNumber.zeroValue 1;
myGenericNumber.add function(x, y) { return x y; };
alert(myGenericNumber.add(myGenericNumber.zeroValue, 1)); // 2 这是对GenericNumber类想当直观的使用你也可能注意到并未限制只能使用number类型。我们可以使用string抑或更复杂的对象。 var stringNumeric new GenericNumberstring();
stringNumeric.zeroValue Hello ;
stringNumeric.add function(x, y) { return x y; };alert(stringNumeric.add(stringNumeric.zeroValue, World)); // Hello World 和接口一样将类型参数放在类之后来告诉我们类的所有属性都是同一个类型。 正如前面类那一节所描述的一个类由两部分组成静态部分和实例部分。泛型类仅属于实例部分所以当我们使用类的时候静态成员不能使用类的类型参数。 泛型的限制 如果你还记得之前的例子有时候你想要写一个泛型函数来操作一组类型并且你是知道这些类型具有什么功能。 在loggingIdentity例子中我们希望能够访问arg的.length属性但是编译器不能确定每个类型都有.length属性所以它将报错提示我们不能这么做。 function loggingIdentityT(arg: T): T {console.log(arg.length); // 错误: T 不存在 .lengthreturn arg;
} 相对于处理任何类型或者所有类型我们更希望强制去要求函数去处理带有.length属性的任何类型或者所有类型。只要该类型有这个成员(属性)我们便运行通过也就是必须包含这个指定的成员(属性)。 既然需要这么做我们就创建一个描述限制的接口。在这里先创建一个只有单个属性.length的接口然后使用这个接口和extends关键字来指明限制 interface hasLength {length: number;
}function loggingIdentityT extends hasLength(arg: T): T {console.log(arg.length); // 现在我们知道它含有.length属性并且不报错return arg;
} 因为这个泛型函数现在是有限制的所以它不在支持任何类型或者所有类型 loggingIdentity(3); // 错误number不包含.length属性 因此我们需要传入其类型具有所需属性的值 loggingIdentity({length: 10, value: 3}); // 正确 在泛型中使用类类型当在TypeScript中使用泛型创建工厂函数的时候需要引用其构造函数的类类型。 class Greeter{greeter:string Hello World;
}
function createT(c: {new(): T}): T { return new c();
}
var newGreeter createGreeter(Greeter);