gpt4 book ai didi

protocols - 在 Swift 中默认实现协议(protocol)时,实现默认属性的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-02 04:20:00 24 4
gpt4 key购买 nike

我对 Swift 中面向协议(protocol)编程的概念着迷,正因为如此,我将去年创建的一个旧项目(最初是一个 OOP 框架)迁移到 POP。

在这个阶段,我遇到的问题可能是因为我对 POP 的理解不正确,或者 Swift 2.0 Beta 不具备创建真正面向协议(protocol)的框架的一切(不太可能 - 如果有的话)可能会误解 POP 的某些方面)。

面向协议(protocol)的编程是不到一个月前向世界推出的全新编程范式,因此关于它的书面内容并不多(我在该主题上发现的only tutorial并没有解决我的问题)我有,WWDC 视频也没有)。

无论如何,重点是:我要么在这里做错了什么,要么面向协议(protocol)编程的缺点之一是你必然会重复很多代码。例证:

我有以下协议(protocol),该协议(protocol)具有许多属性,并且也符合 Equatable 协议(protocol):

protocol MediaType : Equatable {

/// MARK: - Properties

/// The ID of the media, as assigned by MyAnimeList.
var ID: Int { get }

/// The title of the media.
var title: String { get }

/// Other titles by which this anime may be commonly known (only available in details requests).
var otherTitles: (synonyms: [String], english: [String], japanese: [String])? { get }

/// The global ranking of the title (only available in anime details requests).
var rank: Int? { get }

/// Rank of the title based on popularity (number of people adding title to the list) (only available in details requests).
var popularityRank: Int? { get }

/// URL to a representative image of the title. Usually a "cover" image.
var imageURL: String { get }

/// A list of adaptations of this media, or other media on which this media is based (only available in details requests).
var adaptations: Relationships { get }

/// The user's rating of the media.
var memberScore: Float { get }

/// Number of MyAnimeList members that that added the title to their list (only available in details requests).
var membersCount: Int? { get }

/// The number of MyAnimeList members that have this title on their favorites list (only available in details requests).
var favoritedCount: Int? { get }

/// A short HTML-formatted description of the media.
var synopsis: String { get }

/// A list of genres for this title (only available in details requests).
var genres: [String]? { get }

/// Popular tags for the title as assigned by MyAnimeList members (only available in details requests).
var tags: [String] { get }
}

在我的框架的原始版本中,该协议(protocol)是一个名为 Media 的类,以及从它继承的另外两个类。所以他们免费获得了所有这些属性(property)。

但是我似乎无法为符合该协议(protocol)的对象提供这些属性的默认实现(即 getters)?

我尝试的第一件事是简单地将协议(protocol)提供给我的结构声明,但失败了,这是预料之中的,因为我没有提供属性的任何实现:

struct Anime : MediaType {

/// MARK: - MediaType

}

/// Compares two Anime_ objects. Two Anime_ objects are considered equal when they have the same ID and title.
func ==(lhs: Anime, rhs: Anime) -> Bool {
return (lhs.ID == rhs.ID) && (lhs.title == rhs.title)
}

此操作失败:

Type 'Anime' does not conform to protocol 'MediaType'

我的下一个尝试是为 MediaType 编写一个扩展,并在那里抛出属性:

extension MediaType {
/// The ID of the media, as assigned by MyAnimeList.
let ID: Int

/// The title of the media.
let title: String

/// Other titles by which this anime may be commonly known (only available in details requests).
let otherTitles: (synonyms: [String], english: [String], japanese: [String])?

/// The global ranking of the title (only available in anime details requests).
let rank: Int?

/// Rank of the title based on popularity (number of people adding title to the list) (only available in details requests).
let popularityRank: Int?

/// URL to a representative image of the title. Usually a "cover" image.
let imageURL: String

/// A list of adaptations of this media, or other media on which this media is based (only available in details requests).
let adaptations: Relationships

/// The user's rating of the media.
let memberScore: Float

/// Number of MyAnimeList members that that added the title to their list (only available in details requests).
let membersCount: Int?

/// The number of MyAnimeList members that have this title on their favorites list (only available in details requests).
let favoritedCount: Int?

/// A short HTML-formatted description of the media.
let synopsis: String

/// A list of genres for this title (only available in details requests).
let genres: [String]?

/// Popular tags for the title as assigned by MyAnimeList members (only available in details requests).
let tags: [String]
}

这不起作用:

Extensions may not contain stored properties.

它有一个我真的不喜欢的缺点:我已经通过将协议(protocol)的属性复制到扩展中来复制代码。

所以最后,我永远无法将我的属性“传播”到符合协议(protocol)的对象,所以我最终将属性添加到 Anime 结构中。

struct Anime : MediaType {

/// MARK: - MediaType

/// The ID of the media, as assigned by MyAnimeList.
let ID: Int

/// The title of the media.
let title: String

/// Other titles by which this anime may be commonly known (only available in details requests).
let otherTitles: (synonyms: [String], english: [String], japanese: [String])?

/// The global ranking of the title (only available in anime details requests).
let rank: Int?

/// Rank of the title based on popularity (number of people adding title to the list) (only available in details requests).
let popularityRank: Int?

/// URL to a representative image of the title. Usually a "cover" image.
let imageURL: String

/// A list of adaptations of this media, or other media on which this media is based (only available in details requests).
let adaptations: Relationships

/// The user's rating of the media.
let memberScore: Float

/// Number of MyAnimeList members that that added the title to their list (only available in details requests).
let membersCount: Int?

/// The number of MyAnimeList members that have this title on their favorites list (only available in details requests).
let favoritedCount: Int?

/// A short HTML-formatted description of the media.
let synopsis: String

/// A list of genres for this title (only available in details requests).
let genres: [String]?

/// Popular tags for the title as assigned by MyAnimeList members (only available in details requests).
let tags: [String]

/// MARK: - Anime


}

这似乎有效。但现在我在 MediaTypeAnime 中都有我的属性。在 OOP 中,您可以通过子类化来避免重复的代码。

所以我在这里重复我的问题:我是否误解了面向协议(protocol)的编程,或者 POP 的缺点是,每当您使结构/类/枚举符合它时,您都必须复制并粘贴特定于协议(protocol)的逻辑?

最佳答案

我发布这篇文章已经过去几周了,但我相信 Aaron Brager 说的是真的。

虽然面向协议(protocol)编程本身相当新,但协议(protocol)的概念在 Objective-C 中已经存在很长时间了,在 Swift 中也存在,并且在 Java 等语言中也有其变体。由于协议(protocol)和扩展的性质,似乎不可能执行属性的默认实现,因为扩展不允许您在其中设置非计算属性。

关于protocols - 在 Swift 中默认实现协议(protocol)时,实现默认属性的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31224892/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com