向下转型多态和赋值

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.

的范围,该副本就会被丢弃