注意:我已经阅读了苹果文档并研究了一本快速的书。
我对“类型实例方法”之间的区别感到困惑(如果存在,请纠正我,如果我错了)和类型方法?
类方法和实例方法的区别?
类型属性和实例属性之间的区别(如果存在,抱歉我对类型属性主题非常困惑)?
最后,在swift中存在类属性吗?
对于这种困惑感到抱歉:'(
答案 0 :(得分:27)
在Swift中,类型是命名类型或复合类型。 命名类型包括类,结构,枚举和协议。除了用户定义的命名类型之外,Swift还定义了许多命名类型,例如数组,字典和可选值。 (暂时不要忽略复合类型,因为它与你的问题没有直接关系。)
要回答您的问题,假设我创建了一个名为Circle
的用户定义类(这只是一个示例):
class Circle {
static let PI = 3.14
var radius: Double
init(radius: Double) {
self.radius = radius
}
// Returns the area of this circle
func area() {
return PI * radius
}
// Ridiculous class method for demonstration purposes
static func printTypeName() {
println("Circle")
}
}
- 我对"类型实例方法"之间的区别感到困惑。 (如果存在,请纠正我,如果我错了)和类型方法?
醇>
如前所述,类型是指类,结构,枚举,协议和复合类型。在上面的示例中,我使用名为Circle
的类来定义类型。
如果我想构建Circle类的单个对象,那么我将创建一个实例。例如:
let myCircleInstance = Circle(radius: 4.5)
let anotherCircleInstance = Circle(radius: 23.1)
以上是Circle
的对象或实例。现在我可以直接调用它们上的实例方法。我班级中定义的实例方法是area
。
let areaOfMyCircleInstance = myCircleInstance.area()
现在,类型方法是一种可以在类型上直接调用 的方法,而无需创建该类型的实例。
例如:
Circle.printTypeName()
请注意static
之前有一个func
限定符。这表明它直接与类型有关,而不属于该类型的实例。
- 类方法和实例方法的区别?
醇>
见上面的解释。
- 类型属性和实例属性之间的区别(如果是这样的话) 存在,对不起,我对Type Properties主题感到非常困惑)?
醇>
这与您的问题中的一个(除外)类似的解释,它不是应用于方法,而是应用于该类型的属性(即属性,变量)。
在我的Circle
示例中,属性定义为:
static let PI = 3.14
var radius: Double
属性PI
是一个类型属性;它可以通过类型
Circle.PI
属性radius
是该类型的实例属性;它可以由该类型的实例访问。使用我们之前创建的变量:
// I can do this; it will be 4.5
myCircleInstance.radius
// And this; it will be 23.1
anotherCircleInstance.radius
// But I CANNOT do this because radius is an instance property!
Circle.radius
- 最后,在swift中存在类属性吗?
醇>
绝对!请阅读我对上述问题3的解释。我的示例中的PI
属性是类属性的示例。
参考文献:
答案 1 :(得分:3)
不同之处在于为每个实例创建了实例方法和属性。为整个类型
创建类型方法和属性假设您有struct Employee
struct Employee {
static var ID:Int = 0
static var NAME:Int = 1
static func getNameOfField(index:Int) -> String {
var fieldName:String = ""
if index == ID {
fieldName = "Id"
} else if index == NAME {
fieldName = "Name"
}
return fieldName
}
var fields = [Int:String]()
mutating func config(id:String, name:String) {
fields[Employee.ID] = id
fields[Employee.NAME] = name
}
func getField(index:Int) -> String {
return fields[index]!
}
}
var e0 = Employee()
e0.config("1", name: "Mark")
var e1 = Employee()
e1.config("2", name: "John")
print(e0.getField(Employee.NAME)) // prints "Mark"
print(Employee.getNameOfField(Employee.ID)) // prints "Id"
struct e0和e1的每个实例都有属性字段。它是为每个实例创建的,并且存在于其中。存储在fields属性中的值对于每个实例都是不同的。这就是为什么它被称为“实例属性”
每个实例也有方法getField。它是为每个实例创建的,在这种情况下,它可以访问实例的var字段。这就是为什么它被称为“实例方法”
通过引用实例(在我们的示例中为e0和e1)
来访问实例属性和方法ID和NAME是类型属性或静态属性。它们只创建一次,并且对于每个实例和每个其他对象具有相同的值。 您可以通过引用“type”(在我们的示例中为struct)Employee.NAME
来访问类型属性类型方法类似于类型(struct,class,enum)的全局函数。它们通常用于封装绑定到该类型但可能不需要实例的功能。就像在示例中类型方法getNameOfField(index:Int) - > String根据索引返回字段的名称。要返回此信息,您不必创建员工的实例
类型是结构,类和枚举
使用关键字static定义类型方法和属性(这就是为什么它们也称为静态方法和属性)
结构和枚举可以具有类型属性和类型方法。 类只能有类型方法。您可以创建类型属性,但必须是计算
在类中,您可以使用static或class关键字定义类型方法。不同之处在于可以覆盖类方法。
答案 2 :(得分:2)
whyceewhite - 非常感谢你!你澄清了一些我无法理解的东西! 对于那些来到此页面并在Swift 3+上运行的人,如果您想将代码付诸实践并看到静态操作,请参阅下面的代码。
class Circle {
static let PI = 3.14
var radius: Double
init(radius: Double) {
self.radius = radius
}
// Returns the area of this circle
func area() -> Double {
return Double.pi * radius
}
// Ridiculous class method for demonstration purposes
static func printTypeName() {
print("Circle")
}
}
然后开始尝试Circle.printTypeName或上面显示的示例!好东西!
答案 3 :(得分:0)
它是关于范围的,它定义了使用函数的位置和方式的边界。只能在从类初始化对象后才能使用方法。简单地说,为了使用该方法,您必须先创建对象,方法属于该对象。
但是,如果您需要使用方法但不需要启动对象,例如全局设置(例如 CLLocationManager 中的 authorizationStatus()功能,该怎么办?对于GPS坐标授权),您可以创建一个类型方法,只需参考类型名称( NOT 对象名称),然后是经典的doc函数调用。< / p>
答案 4 :(得分:0)
class Circle {
//static let PI = 3.14 -> error: static member 'PI' cannot be used on instance of type 'Circle'
let PI: Double = 3.1415
var radius: Double
init (radius: Double) {
self.radius = radius
}
// Return the area of this Circle
func area() -> Double {
return PI * radius
}
// Radius class method for demonstration purposes
static func printTypeName() {
print("Circle")
}
}
let myCircleInstance = Circle(radius: 4.5)
let anotherCircleInstance = Circle(radius: 23.1)
Circle.printTypeName() // Circle
print(myCircleInstance.area()) // 14.13675
print(anotherCircleInstance.area()) // 72.56865
//