类型方法和类型实例方法等之间的区别?

时间:2015-09-14 21:54:34

标签: swift types properties

注意:我已经阅读了苹果文档并研究了一本快速的书。

  1. 我对“类型实例方法”之间的区别感到困惑(如果存在,请纠正我,如果我错了)和类型方法?

  2. 类方法和实例方法的区别?

  3. 类型属性和实例属性之间的区别(如果存在,抱歉我对类型属性主题非常困惑)?

  4. 最后,在swift中存在类属性吗?

  5. 对于这种困惑感到抱歉:'(

5 个答案:

答案 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")
    }
} 
  
      
  1. 我对"类型实例方法"之间的区别感到困惑。   (如果存在,请纠正我,如果我错了)和类型方法?
  2.   

如前所述,类型是指类,结构,枚举,协议和复合类型。在上面的示例中,我使用名为Circle来定义类型

如果我想构建Circle类的单个对象,那么我将创建一个实例。例如:

let myCircleInstance = Circle(radius: 4.5)
let anotherCircleInstance = Circle(radius: 23.1)

以上是Circle的对象或实例。现在我可以直接调用它们上的实例方法。我班级中定义的实例方法area

let areaOfMyCircleInstance = myCircleInstance.area()

现在,类型方法是一种可以在类型上直接调用 的方法,而无需创建该类型的实例

例如:

Circle.printTypeName()

请注意static之前有一个func限定符。这表明它直接与类型有关,而不属于该类型的实例。

  
      
  1. 类方法和实例方法的区别?
  2.   

见上面的解释。

  
      
  1. 类型属性和实例属性之间的区别(如果是这样的话)   存在,对不起,我对Type Properties主题感到非常困惑)?
  2.   

这与您的问题中的一个除外)类似的解释,它不是应用于方法,而是应用于该类型的属性(即属性,变量)。

在我的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
  
      
  1. 最后,在swift中存在类属性吗?
  2.   

绝对!请阅读我对上述问题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)

@phyceewhite示例的@PaperBart1修复有点棘手,因为他将声明的PI替换为swift常见的默认值。 我为Swift 4改写了这个例子:

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

 //