У меня есть набор моделей Realm, которые я хочу записать в модуле, и только для чтения вне модуля.
Я начал с иерархии классов (организационная иерархия, а не наследование), которая выглядела примерно так:
@objcMembers class Section: Object {
dynamic var number: Int = 0
dynamic var name: String = ""
let subsections = List<Subsection>()
}
Было довольно просто получить видимость, которую я хотел, для самих классов и для управляемых Царством dynamic var
свойств:
@objcMembers public class Section: Object {
public internal(set) dynamic var number: Int = 0
public internal(set) dynamic var name: String = ""
// ...
}
Однако ребенок Lists
представляет большую проблему. Как таковой, список объявлен let
, поэтому само поле доступно только для чтения; но само Царство List
изменчиво. После некоторых копаний в источнике Realm и нескольких типичных ложных запусках ( при попытке использовать протоколы со связанными типами в качестве типов возврата и т. Д.) Я нажал на обертку Lists
(которая соответствует RandomAccessCollection
) в AnyRandomAccessCollection
:
internal let _subsections = List<Subsection>()
public func subsections() -> AnyRandomAccessCollection<Subsection> {
return AnyRandomAccessCollection(_subsections)
}
Когда я пытаюсь обновить свои модульные тесты, некоторые из которых обращаются к List
с индексами Int
:
// Good
let subsections: List<Subsection> = section.subsections
let subsection0: Subsection = subsections[0]
Я получаю
// Bad
let subsections: AnyRandomAccessCollection<Subsection> = section.subsections()
let subsection0: Subsection = subsections[0]
не может индексировать значение типа 'AnyRandomAccessCollection ' с индексом типа 'Int'
Я довольно новичок в Swift и все еще постоянно сбиваюсь с толку из-за своего общего опыта в Java и C #, но казалось, что основная проблема заключалась в том, что Collection
объявляет два связанных типа, Element
и Index
, но AnyCollection
предоставляет только Element
в качестве общего параметра. После еще одного рытья я нашел AnyIndex
и нажал на следующее:
let subsections: AnyRandomAccessCollection<Subsection> = section.subsections()
let subsection0: Subsection = subsections[AnyIndex(0)]
Это работает, тесты проходят, но, кажется, довольно бананы. Для меня не очевидно , почему это работает (сработало бы, если бы базовый List
не был подписан Int
?), И это противоречит интуитивно любому, кто наивно пытается использовать возвращаемый объект. Я почти чувствую, что мне лучше написать свой собственный класс-оболочку, соответствующий протоколу RandomAccessCollection
, за исключением того, что я не хочу идти дальше по пути реализации десятков сквозных методов.
Действительно ли это самый простой способ выставить Царство List
(или какой-либо другой RandomAccessCollection
) как доступное только для чтения RandomAccessCollection
со связанными типами элементов и индексов? Или есть какое-то более простое решение на основе обобщений или стирания типов, о котором я не знаю?