Swift Generics эквивалент Java любого типа <?>

В Java вы можете иногда использовать дженерики, не заботясь о реальном типе. Вы можете сделать это в Swift?

Например MyClass<AnyObject> не работает как MyClass<?> будет на Яве. На я бы ожидал, что это будет работать так же.

Есть ли другой путь?

2 ответа

Решение

Введите параметр типа; компилятор позволит ему принять любой тип. Пытаться:

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 на что бы то ни было; Вы можете сделать APIRequest скажем, на Resource,

protocol Resource {}
class Movie : Resource {}
class Song : Resource {}

class APIRequest<T:Resource> { /* ... */ }

func executeRequest<T:Resource> (request: APIRequest<T>) { /* ... */ } 

В Swift нет аналога. Обобщения в Swift несколько отличаются от Java в целом, поэтому варианты использования также различны. Обобщения в Swift очень хороши для создания общих полезных конструкций и функций. Если вы планируете разрабатывать классы с предполагаемым наследованием вокруг Generics, будьте очень осторожны с вашим дизайном заранее и рассмотрите альтернативы. Это может быть довольно сложно. Существуют фундаментальные различия в двух языках, поэтому попытка сохранить паритет в коде может оказаться сложной. Некоторые требования приведут к принципиально различным решениям на двух языках.

Вот несколько возможных вариантов в зависимости от специфики вашей проблемы:

// 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)
Другие вопросы по тегам