Предоставление списка областей как (только для чтения) RandomAccessCollection - PullRequest
0 голосов
/ 05 июля 2018

У меня есть набор моделей 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 со связанными типами элементов и индексов? Или есть какое-то более простое решение на основе обобщений или стирания типов, о котором я не знаю?

...