向下转型多态和赋值
Downcasting Polymorphism and assignments
我创建了一个玩具问题来理解为什么我无法在向下转换后设置 属性 的值。问题出在视图控制器 #3 中:我想为 属性 artist
赋值。
import Foundation
protocol MediaType {
var year: String? { get set }
}
struct Song: MediaType {
var artist: String?
var musicians: [String]?
// Implement Protocol `MediaType`
var year: String?
}
class MediaStateController {
var media: MediaType?
}
//
// view controller 1: controller does not know the media type just yet.
//
let stateController = MediaStateController() // media remains nil for now
print(stateController.media is Song) // false
//
// view controller 2: knows the media type so it can assign the media type.
//
stateController.media = Song()
print(stateController.media is Song) // true
print(stateController.media as? Song) // Optional(Song(artist: nil, musicians: nil, year: nil))
print(stateController.media) // Optional(Song(artist: nil, musicians: nil, year: nil))
print(type(of: stateController.media)) // Optional<MediaType>
// view controller 3: knows only the artist name but not the musicians.
if var song = stateController.media as? Song {
song.artist = "SomeArtist" // ISSUE: this does not set the value (see print-out below)
}
print(stateController.media as? Song) // Optional(Song(artist: nil, musicians: nil, year: nil))
if var song = stateController.media as? Song {
// makes no sense to not use song, but let's do it anyway.
// (stateController.media as? Song)?.artist = "SomeArtist" // error: cannot assign to immutable expression of type 'String?'
}
print(stateController.media as? Song) // Optional(=Song(artist: nil, musicians: nil, year: nil))
if var song = stateController.media as? Song {
// THIS DOES SET THE VALUE, but why?
song.artist = "SomeArtist"
stateController.media = song
}
print(stateControllaer.media as? Song) // Optional(Song(artist: Optional("SomeArtist"), musicians: nil, year: nil))
Song
是一个struct,在Swift中是一个值类型。在这个例子中:
// view controller 3: knows only the artist name but not the musicians.
if var song = stateController.media as? Song {
song.artist = "SomeArtist" // ISSUE: this does not set the value (see print-out below)
}
您正在将原始 Song
实例复制到新变量中,然后更新该副本的 artist
属性。一旦您退出 if var
.
的范围,该副本就会被丢弃
我创建了一个玩具问题来理解为什么我无法在向下转换后设置 属性 的值。问题出在视图控制器 #3 中:我想为 属性 artist
赋值。
import Foundation
protocol MediaType {
var year: String? { get set }
}
struct Song: MediaType {
var artist: String?
var musicians: [String]?
// Implement Protocol `MediaType`
var year: String?
}
class MediaStateController {
var media: MediaType?
}
//
// view controller 1: controller does not know the media type just yet.
//
let stateController = MediaStateController() // media remains nil for now
print(stateController.media is Song) // false
//
// view controller 2: knows the media type so it can assign the media type.
//
stateController.media = Song()
print(stateController.media is Song) // true
print(stateController.media as? Song) // Optional(Song(artist: nil, musicians: nil, year: nil))
print(stateController.media) // Optional(Song(artist: nil, musicians: nil, year: nil))
print(type(of: stateController.media)) // Optional<MediaType>
// view controller 3: knows only the artist name but not the musicians.
if var song = stateController.media as? Song {
song.artist = "SomeArtist" // ISSUE: this does not set the value (see print-out below)
}
print(stateController.media as? Song) // Optional(Song(artist: nil, musicians: nil, year: nil))
if var song = stateController.media as? Song {
// makes no sense to not use song, but let's do it anyway.
// (stateController.media as? Song)?.artist = "SomeArtist" // error: cannot assign to immutable expression of type 'String?'
}
print(stateController.media as? Song) // Optional(=Song(artist: nil, musicians: nil, year: nil))
if var song = stateController.media as? Song {
// THIS DOES SET THE VALUE, but why?
song.artist = "SomeArtist"
stateController.media = song
}
print(stateControllaer.media as? Song) // Optional(Song(artist: Optional("SomeArtist"), musicians: nil, year: nil))
Song
是一个struct,在Swift中是一个值类型。在这个例子中:
// view controller 3: knows only the artist name but not the musicians.
if var song = stateController.media as? Song {
song.artist = "SomeArtist" // ISSUE: this does not set the value (see print-out below)
}
您正在将原始 Song
实例复制到新变量中,然后更新该副本的 artist
属性。一旦您退出 if var
.