Swift 等价于 Java 任何类型的泛型 <?>
Swift Generics equivalent of Java any type <?>
在 Java 中,有时您可以使用泛型而不关心实际类型。
你能在 Swift 中做到吗?
例如 MyClass<AnyObject>
不像 MyClass<?>
在 Java 中那样工作。我希望它能起到同样的作用。
还有其他方法吗?
Swift 中没有对应项。 Swift 中的泛型通常与 Java 中的泛型有些不同,因此用例也不同。 Swift 中的泛型非常适合制作通用的实用程序结构和函数。如果您正在考虑设计 类 并围绕泛型进行预期的继承,请在设计前非常小心并考虑替代方案。这可能非常具有挑战性。这两种语言存在根本差异,因此试图在代码中保持对等可能会很困难。某些要求会导致两种语言的解决方案根本不同。
根据您的问题的具体情况,这里有一些可能的选项:
// start with a common protocol
protocol Requestable {
func execute()
func processData(input: Any)
}
// protocol with type constraint
protocol APIRequest : Requestable {
typealias ContentType
var content : ContentType { get }
func processInput(input: ContentType)
}
extension APIRequest {
func processData(input: Any) {
if let input = input as? ContentType {
processInput(input)
} else {
// probably should throw an error here
}
}
}
// Either define a Generic function to execute with a specific type
func executeRequest<RequestType:APIRequest>(request: RequestType) {
request.execute()
}
// Or define a function taking a protocol conforming type
func executeRequest(request: Requestable) {
request.execute()
}
// process the data with a specific request and input
func processRequest<RequestType:APIRequest>(request: RequestType, input: RequestType.ContentType) {
request.processInput(input)
}
// process the data with input of arbitrary type
func processRequest(request: Requestable, data: Any) {
request.processData(data)
}
class Movie {
}
class MovieRequest : APIRequest {
var content : Movie
init(movie: Movie) {
self.content = movie
}
func execute() {
// do something here
}
func processInput(input: Movie) {
// do something with the movie input
}
}
let movieRequest = MovieRequest(movie: Movie())
executeRequest(movieRequest)
引入一个类型参数;编译器会让它接受任何类型。尝试:
func executeRequest<T> (request: APIRequest<T>) {
// ...
}
例如:
class APIRequest<T> {}
class Movie {}
class MovieRequest : APIRequest<Movie> {}
let m = MovieRequest()
//print(m)
func executeRequest<T> (request: APIRequest<T>) {
print(request)
}
executeRequest(m)
类型参数的引入允许更明确和更好地匹配问题域。例如,在你的情况下,你肯定不能对任何事情做 APIRequest
;你可以在 Resource
.
上做一个 APIRequest
protocol Resource {}
class Movie : Resource {}
class Song : Resource {}
class APIRequest<T:Resource> { /* ... */ }
func executeRequest<T:Resource> (request: APIRequest<T>) { /* ... */ }
在 Java 中,有时您可以使用泛型而不关心实际类型。 你能在 Swift 中做到吗?
例如 MyClass<AnyObject>
不像 MyClass<?>
在 Java 中那样工作。我希望它能起到同样的作用。
还有其他方法吗?
Swift 中没有对应项。 Swift 中的泛型通常与 Java 中的泛型有些不同,因此用例也不同。 Swift 中的泛型非常适合制作通用的实用程序结构和函数。如果您正在考虑设计 类 并围绕泛型进行预期的继承,请在设计前非常小心并考虑替代方案。这可能非常具有挑战性。这两种语言存在根本差异,因此试图在代码中保持对等可能会很困难。某些要求会导致两种语言的解决方案根本不同。
根据您的问题的具体情况,这里有一些可能的选项:
// start with a common protocol
protocol Requestable {
func execute()
func processData(input: Any)
}
// protocol with type constraint
protocol APIRequest : Requestable {
typealias ContentType
var content : ContentType { get }
func processInput(input: ContentType)
}
extension APIRequest {
func processData(input: Any) {
if let input = input as? ContentType {
processInput(input)
} else {
// probably should throw an error here
}
}
}
// Either define a Generic function to execute with a specific type
func executeRequest<RequestType:APIRequest>(request: RequestType) {
request.execute()
}
// Or define a function taking a protocol conforming type
func executeRequest(request: Requestable) {
request.execute()
}
// process the data with a specific request and input
func processRequest<RequestType:APIRequest>(request: RequestType, input: RequestType.ContentType) {
request.processInput(input)
}
// process the data with input of arbitrary type
func processRequest(request: Requestable, data: Any) {
request.processData(data)
}
class Movie {
}
class MovieRequest : APIRequest {
var content : Movie
init(movie: Movie) {
self.content = movie
}
func execute() {
// do something here
}
func processInput(input: Movie) {
// do something with the movie input
}
}
let movieRequest = MovieRequest(movie: Movie())
executeRequest(movieRequest)
引入一个类型参数;编译器会让它接受任何类型。尝试:
func executeRequest<T> (request: APIRequest<T>) {
// ...
}
例如:
class APIRequest<T> {}
class Movie {}
class MovieRequest : APIRequest<Movie> {}
let m = MovieRequest()
//print(m)
func executeRequest<T> (request: APIRequest<T>) {
print(request)
}
executeRequest(m)
类型参数的引入允许更明确和更好地匹配问题域。例如,在你的情况下,你肯定不能对任何事情做 APIRequest
;你可以在 Resource
.
APIRequest
protocol Resource {}
class Movie : Resource {}
class Song : Resource {}
class APIRequest<T:Resource> { /* ... */ }
func executeRequest<T:Resource> (request: APIRequest<T>) { /* ... */ }