Swift 协议、结构,但没有具体类型
好的,我有一个名为Swift 协议、结构,但没有具体类型,swift,generics,protocols,Swift,Generics,Protocols,好的,我有一个名为Environment protocol Environment { var rootURL: String {get} } 然后是两个结构: struct Production: Environment { var rootURL = "www.api.mybackend.com/v1" } struct Development: Environment { var rootURL = "www.api.mydevelopmentbackend.com/v1"
Environment
protocol Environment {
var rootURL: String {get}
}
然后是两个结构:
struct Production: Environment {
var rootURL = "www.api.mybackend.com/v1"
}
struct Development: Environment {
var rootURL = "www.api.mydevelopmentbackend.com/v1"
}
具有检索环境的函数的设置对象:
class Settings {
func getEnvironment<T>() -> T where T: Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 0:
return Development() as! T
case 1:
return Production() as! T
default:
return Development() as! T
}
}
func retreiveEnvironmentFromLocalStore() -> Int {
//Realm, SQLLite, Core Date, I don't really care for this example.
//Let's just say it defaults to returning 1
}
}
类设置{
func getEnvironment()->T其中T:Environment{
让environmentRaw=self.retreiveEnvironmentFromLocalStore()
交换机环境RAW{
案例0:
将Development()返回为!T
案例1:
将生产()返回为!T
违约:
将Development()返回为!T
}
}
func RetreiveEnvironment fromLocalStore()->Int{
//Realm、SQLLite、Core Date,我并不真正关心这个示例。
//假设它默认返回1
}
}
我真的很想继续前进,但现在当我在设置对象上调用此函数并尝试使用rootURL
属性时,编译器抱怨它无法识别类型。因此,为了更好地理解并找到解决方案:
1) 如果我正在访问由协议定义的属性,而它至少知道返回的类型符合该协议,那么为什么它会关心该类型
2) 结构没有继承性。我应该定义一个基类而忘记泛型吗
3) 我可以使我的getEnvironment
功能更好吗?我不喜欢强制铸造,它看起来像一种代码气味
4) 我在这里正确使用泛型了吗
编辑1:
要明确的是,我想要一个函数,它返回一个我知道将具有此属性的结构
我在这里正确使用泛型了吗
不,我不这么认为。您的意思是getEnvironment
将返回T
,它可以是客户机代码指定的任何类型,只要它实现Environment
。然而,该方法的实现并没有做到这一点。它只返回两种环境
s,返回哪种类型不取决于客户端代码。返回的类型取决于retreiveenvironmentfromloctore
返回的内容。因此,泛型不适用于这种情况
因为它返回的环境类型是由方法的实现决定的,而不是由客户机代码决定的,所以您应该在这里使用多态性-让它返回一个环境
:
func getEnvironment() -> Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 0:
return Development()
case 1:
return Production()
default:
return Development()
}
}
我在这里正确使用泛型了吗
不,我不这么认为。您的意思是getEnvironment
将返回T
,它可以是客户机代码指定的任何类型,只要它实现Environment
。然而,该方法的实现并没有做到这一点。它只返回两种环境
s,返回哪种类型不取决于客户端代码。返回的类型取决于retreiveenvironmentfromloctore
返回的内容。因此,泛型不适用于这种情况
因为它返回的环境类型是由方法的实现决定的,而不是由客户机代码决定的,所以您应该在这里使用多态性-让它返回一个环境
:
func getEnvironment() -> Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 0:
return Development()
case 1:
return Production()
default:
return Development()
}
}
我真的希望继续朝着面向协议的编程方向前进
相反,我建议您尝试朝着一个清晰、可理解的代码方向前进,而不管流行方向是什么
以下是您的函数声明:
func getEnvironment()->T其中T:Environment
这意味着getEnvironment()
将返回某种类型的对象T
,其中T
在编译时根据调用getEnvironment()
的代码推导而来
T
可以是什么类型?它可以是生产
或开发
。例如,您可以编写:
let e: Production = Settings().getEnvironment()
这使编译器可以推断getEnvironment()
在此调用站点返回一个Production
(这是一个环境
)
但是有一个问题:getEnvironment()
可能会根据retreiveEnvironment fromLocalStore
中的随机数生成器,尝试返回一个Development
。然后,当它无法将Development
转换为Production
时,您将在运行时得到崩溃
为什么您认为getEnvironment()
需要通用?根据你问题中的代码,它不应该是
import Foundation
protocol Environment {
var rootURL: String {get}
}
struct Production: Environment {
var rootURL = "www.api.mybackend.com/v1"
}
struct Development: Environment {
var rootURL = "www.api.mydevelopmentbackend.com/v1"
}
class Settings {
func getEnvironment() -> Environment {
let environmentRaw = self.retreiveEnvironmentFromLocalStore()
switch environmentRaw {
case 1: return Production()
default: return Development()
}
}
func retreiveEnvironmentFromLocalStore() -> Int {
return Int(arc4random())
}
}
let settings = Settings()
let e = settings.getEnvironment()
款式说明:建议我们
- 根据其副作用命名函数和方法
- 那些没有副作用的应该读作名词短语,例如
x.distance(to:y),i.succession()
- 那些没有副作用的应该读作名词短语,例如
Settings
中的方法有重要的副作用,否则更好的名称应该是environment()
和rawEnvironmentFromLocalStore()
我真的希望继续朝着面向协议的编程方向前进
相反,我建议您尝试朝着一个清晰、可理解的代码方向前进,而不管流行方向是什么
以下是您的函数声明:
func getEnvironment()->T其中T:Environment
这意味着getEnvironment()
将返回某种类型的对象T
,其中T
在编译时根据调用getEnvironment()
的代码推导而来
T
可以是什么类型?它可以是生产
或开发
。例如,您可以编写:
let e: Production = Settings().getEnvironment()
这使编译器可以推断getEnvironment()
在此调用站点返回一个Production
(这是一个环境
)
但是有一个问题:getEnvironment()
可能会根据retreiveEnvironment fromLocalStore
中的随机数生成器,尝试返回一个Development
。然后,在运行时,当它无法强制转换时,您将得到一个崩溃