Почему в Swift не используются скобки вместо ассоциированных типов? [Дубликат]

Самое простое решение - создать функцию JavaScript и вызвать его для обратного вызова Ajax success.

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);    
}); 
32
задан orome 24 October 2014 в 20:31
поделиться

2 ответа

Это было рассмотрено несколько раз в devlist. Основной ответ заключается в том, что связанные типы более гибкие, чем параметры типа. Хотя у вас есть конкретный случай здесь одного параметра типа, вполне возможно иметь несколько. Например, коллекции имеют тип элемента, но также тип индекса и тип генератора. Если вы специализируетесь на них полностью с параметризацией типа, вам придется говорить о таких вещах, как Array<String, Int, Generator<String>> или тому подобное.

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

Независимо от того, стоит ли эта дополнительная мощность, это совершенно другой вопрос, и только время покажет. Но связанные типы определенно более мощные, чем простая параметризация типа.

23
ответ дан Rob Napier 1 September 2018 в 08:44
поделиться

Ответ RobNapier (как обычно) неплохой, но только для альтернативной перспективы, которая может оказаться еще более просветляющей ...

О связанных типах

Протокол представляет собой абстрактный набор требований - контрольный список, который должен выполнить конкретный тип, чтобы сказать, что он соответствует протоколу. Традиционно считается, что этот контрольный список поведения: методы или свойства, реализованные конкретным типом. Связанные типы - это способ наименования вещей, которые участвуют в таком контрольном списке, и тем самым расширяя определение, сохраняя при этом его открытый конец как , как соответствующий тип реализует соответствие.

Когда вы видите:

protocol SimpleSetType {
    associatedtype Element
    func insert(_ element: Element)
    func contains(_ element: Element) -> Bool
    // ...
}

Что означает, что для типа, требующего соответствия SimpleSetType, не только этот тип содержит функции insert(_:) и contains(_:), эти две функции должны принимать тот же тип параметра, что и друг друга. Но не имеет значения, каков тип этого параметра.

Вы можете реализовать этот протокол с помощью общего или нестандартного типа:

class BagOfBytes: SimpleSetType {
    func insert(_ byte: UInt8) { /*...*/ }
    func contains(_ byte: UInt8) -> Bool { /*...*/ }
}

struct SetOfEquatables<T: Equatable>: SimpleSetType {
    func insert(_ item: T) { /*...*/ }
    func contains(_ item: T) -> Bool { /*...*/ }
}    

Обратите внимание, что нигде BagOfBytes или SetOfEquatables определяют соединение между SimpleSetType.Element и типом, используемым в качестве параметра для их двух методов - компилятор автоматически выполняет то, что эти типы связаны с правильными методами, поэтому они отвечают требованиям протокола для связанного типа .

В параметрах общего типа

Если связанные типы расширяют ваш словарь для создания абстрактных контрольных списков, параметры типового типа ограничивают реализацию конкретного типа. Когда у вас есть общий класс:

class ViewController<V: View> {
    var view: V
}

Он не говорит, что существует множество разных способов сделать ViewController (пока у вас есть view), это говорит, что ViewController - настоящая конкретная вещь , и она имеет view. Кроме того, мы точно не знаем, какой вид имеет данный экземпляр ViewController, но мы знаем, что он должен быть View (либо подклассом класса View, либо типом, реализующим View ... мы не говорим).

Или, говоря иначе, писать общий тип или функцию - это своего рода ярлык для написания реального кода. Возьмем этот пример:

func allEqual<T: Equatable>(a: T, b: T, c: T) {
    return a == b && b == c
}

Это имеет такой же эффект, как если бы вы проходили все типы Equatable и писали:

func allEqual(a: Int, b: Int, c: Int) { return a == b && b == c }
func allEqual(a: String, b: String, c: String) { return a == b && b == c }
func allEqual(a: Samophlange, b: Samophlange, c: Samophlange) { return a == b && b == c }

Как вы можете видеть, re , создавая код здесь, реализуя новое поведение - в отличие от связанных с протоколом типов, где мы описываем только требования к выполнению чего-то другого.

TLDR

] Ассоциированные типы и параметры типового типа - это очень разные виды инструментов: связанные типы - это язык описания, а generics - язык реализации. У них очень разные цели, хотя их использование иногда выглядит одинаково (особенно когда речь идет о тонких взглядах на такие взгляды между абстрактным планом для коллекций любого типа элемента и фактическим типом коллекции, который все еще может иметь общий элемент). Поскольку они очень разные звери, у них есть другой синтаксис.

20
ответ дан rickster 1 September 2018 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: