下行多态性和赋值

问题描述 投票:0回答:1

我创建了一个玩具问题,以了解为什么向下转换后无法设置属性的值。问题出在视图控制器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))
swift downcast
1个回答
0
投票

Song是一个结构,这是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的范围,该副本就会被丢弃。

© www.soinside.com 2019 - 2024. All rights reserved.