2016-03-08 2 views
1

Apple, дает нам пример понижающее приведение объекта одного и того же типа, как, например:Как сбрасывать объект, который может быть нескольких типов?

let someObjects: [AnyObject] = [ 
    Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), 
    Movie(name: "Moon", director: "Duncan Jones"), 
    Movie(name: "Alien", director: "Ridley Scott") 
] 

Затем мы можем получить доступ к каждому отдельному атрибуту путем создания абстрактной переменной «объекта» и приведения его в то, что мы ожидаем, что это будет (фильм):

for object in someObjects { 
    let movie = object as! Movie 
    print("Movie: '\(movie.name)', dir. \(movie.director)") 
} 

Но что, если мы переходим к следующему уровню и, например, у нас есть подклассы фильмов:

немого кино

Comedy

Действие

Каждый из которых все имеют одинаковые атрибуты - имя & директор

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

+0

Можете ли вы показать код, как вы пытались сделать подклассы таким же образом? – ronatory

+0

Я не могу воспроизвести вашу проблему. Он отлично работает, когда я пытаюсь это сделать (не то, что это хорошая идея. Вам не нужно «AnyObject» очень часто, и вы должны избегать подклассов и down-casting, если вы можете их избежать.) В качестве комментариев покажите код, который * не работает *, а не только код, который * делает *. –

+0

Не забудьте вернуться и принять ответ или проголосовать за ответы, которые вам помогли. – JAL

ответ

0

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

// here the subclass SilentFilm 
class SilentFilm:Movie { 

} 

// Here the array with SilentFilm objects 
let someOtherObjects: [AnyObject] = [ 
    SilentFilm(name: "silentname", director: "silentdirector"), 
    SilentFilm(name: "silentname2", director: "silentdirector2") 
] 

for object2 in someOtherObjects { 
    // Here the cast to Movie like in your example 
    let movie = object2 as! Movie 
    // or cast to SilentFilm works also 
    // let movie = object2 as! SilentFilm 
    print("Movie: '\(movie.name)', dir. \(movie.director)") 
} 

// Expected Output 
// Movie: 'silentname', dir. silentdirector 
// Movie: 'silentname2', dir. silentdirector2 

Поправьте меня, если я missunderstood ваши вопросы!

0

Почему бы не создать иерархию классов с родительским классом Movie и проверить тип фильма во время итерации через массив? Нет необходимости принудительно использовать cast from AnyObject, если вы укажете свой массив, содержащий Movie объектов, и у вас есть все ваши поджанры от Movie.

class Movie { 
    var name: String! 
    var director: String! 

    init(name: String, director: String) { 
     self.name = name 
     self.director = director 
    } 
} 

class Comedy: Movie { 
    var laughTrack: Bool! 

    init(name: String, director: String, laughTrack: Bool) { 
     super.init(name: name, director: director) 
     self.laughTrack = laughTrack 
    } 
} 

let someObjects: [Movie] = [ 
    Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), 
    Movie(name: "Moon", director: "Duncan Jones"), 
    Movie(name: "Alien", director: "Ridley Scott"), 
    Comedy(name: "Caddyshack", director: "Harold Ramis", laughTrack: false) 
] 

for movie in someObjects { 
    if movie is Comedy { 
     print("\(movie.name) is a comedy") 
    } else { 
     print("\(movie.name) is a movie") 
    } 
} 

Выход:

2001: A Space Odyssey это фильм

Луна фильм

Иностранец это фильм

Caddyshack комедия