2015-01-31 2 views
1

В Swift я объявила функцию, которая отличается от Array.count только тем, что если array == nil функция возвращает 0. Это связано с моим UITableViewDataSource, но это не важно здесь. Проблема заключается в том, если я объявляю функции, как:Pass Array, содержащий класс или структуру

class func countOfItemsInArray(array: [AnyObject]?) -> Int 

, а затем попытаться передать ему массив структур, он заявляет, что в Структуры массива не соответствуют AnyObject. Я понимаю, почему это (я думаю), но есть ли способ сделать эту работу с классами и структурами, или мне нужно просто скопировать и вставить?

ответ

0

Если вы используете Any вместо AnyObject вы можете передать любой тип, так также: Структуры

class func countOfItemsInArray(array: [Any]?) -> Int 

Это немного странно.

Я использовал эту функцию:

func countOfItemsInArray(array: [Any]?) -> Int { 
    return array != nil ? array!.count : 0 
} 

Заявленный два ваших Assignment структур и поместить их в массив:

let structOne = Assignment(name: "1", dueDate: NSDate(), subject: "1") 
let structTwo = Assignment(name: "2", dueDate: NSDate(), subject: "2") 
let myArray: [Assignment] = [structOne, structTwo] 

Но вот интересная часть.
При вызове println(countOfItemsInArray(myArray)) он выдает ошибку:

<stdin>:27:33: error: 'Assignment' is not identical to 'Any' 
println(countOfItemsInArray(myArray)) 
^ 
<stdin>:17:26: note: in initialization of parameter 'array' 
func countOfItemsInArray(array: [Any]?) -> Int { 
^ 

Так я тестировал, если myArray имеет типа [Any]:

println(myArray is [Any]) 

, к которому скоро говорят:

<stdin>:25:17: error: 'Any' is not a subtype of 'Assignment' 
println(myArray is [Any]) 
^ 

Но когда я изменяю аннотация типа myArray до [Any] работает:

let myArray: [Any] = [structOne, structTwo] 

И когда просто передав буквальную функцию он работает, тоже:

countOfItemsInArray([structOne, structTwo]) 

Весь пример кода можно увидеть here.

+0

Я получаю сообщение об ошибке, «„myStructType“не совпадает с 'Любые» – PopKernel

+0

Не могли бы вы опубликовать код (или ссылку к нему)? –

+0

Несомненно. Функция находится здесь: http://pastebin.com/cztjMbFW – PopKernel

3

Дженерики, вероятно, лучше подходят для этой проблемы, чем полагаться на ковариацию [AnyObject]. Версия countElements, которая работала на факультативном массив и возвращается 0 в случае nil может идти, как это:

func countElements<T>(array: [T]?) -> Int { 
    return array?.count ?? 0 
} 

При вызове countElements с любым типом массива, заполнитель T заменяется типом элемента содержащихся в массиве.

Обратите внимание: эта версия перегружает существующие countElements версией, которая приобретает дополнительный вариант. Если вы вызываете его с помощью необязательной или какой-либо другой коллекции, будет вызываться версия Swift, если вы передадите дополнительный массив, этот вызов будет вызван.Это спорный вопрос, является ли это хорошая практика (я думаю, что это хорошо) или плохой (некоторые из них могут не одобряю :).

версия, которая работает на любом типе коллекции будет:

func countElements<C: CollectionType>(col: C?) -> C.Index.Distance { 
    return col.map { countElements($0) } ?? 0 
} 
+0

Ваше решение с дженериками является совершенным. Однако я среди тех, кто избегает переопределения стандартной функции Swift. Более конкретно, я признаю, что не знаю, может ли Cocoa (и другие библиотеки/рамки ОС) видеть вашу версию countElements. Если возможно, подход с переопределением немного небезопасен. –

+0

Нет никакого риска от Cocoa (даже если бы это была вероятность, которую я подозреваю, это не так), назвав эту версию, поскольку версия Swift опережает ее в приоритете разрешения перегрузки (хотя Swift будет неявно повышать преобразование не-опций в опции , звонки, которые требуют, чтобы они выглядели ниже в иерархическом порядке). Я не стал бы перегружать существующую функцию таким образом, чтобы вызвать неоднозначность для существующих абонентов (хотя, я думаю, вы могли бы сделать это невольно). –

+0

ОК в своем заявлении вы не использовали «общедоступный» модификатор контроля доступа. Таким образом, ваша версия ** countElements ** видима только внутри проекта, где она объявлена. Тогда это не должно мешать другой библиотеке. –

Смежные вопросы