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

问题描述 投票:12回答:5

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

  1. 我对“类型实例方法”(如果存在,如果我错了,请纠正我)和类型方法之间的区别感到困惑?
  2. 类方法和实例方法的区别?
  3. 类型属性和实例属性之间的区别(如果存在,抱歉我对类型属性主题非常困惑)?
  4. 最后,Do类属性是否存在于swift中?

对困惑感到抱歉 :'(

swift types properties
5个回答
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. 我对“类型实例方法”(如果存在,如果我错了,请纠正我)和类型方法之间的区别感到困惑?

如前所述,类型是指类,结构,枚举,协议和复合类型。在上面的例子中,我使用一个名为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. 类方法和实例方法的区别?

见上面的解释。

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

这与您的问题1中的解释类似,不同之处在于它不是应用于方法,而是应用于该类型的属性(即属性,变量)。

在我的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. 最后,Do类属性是否存在于swift中?

绝对!请阅读我对上述问题3的解释。我的示例中的PI属性是类属性的示例。

参考文献:


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根据索引返回字段的名称。要返回此信息,您不必创建员工的na实例

类型是结构,类和枚举

您可以使用关键字static定义类型方法和属性(这就是为什么它们也称为静态方法和属性)

结构和枚举可以具有类型属性和类型方法。类只能有类型方法。您可以创建类型属性,但它必须是计算的

在类中,您可以使用static或class关键字定义类型方法。不同之处在于可以覆盖类方法。


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或上面显示的示例!好东西!


0
投票

它是关于范围的,它定义了使用函数的位置和方式的边界。只能在从类初始化对象后才能使用方法。简单地说,为了使用该方法,您必须先创建对象,方法属于该对象。

但是,如果您需要使用方法但不需要启动对象,例如全局设置(例如CLLocationManager中的用于GPS坐标授权的authorizationStatus()函数),则可以创建类型方法并简单地通过引用到类型名称(NOT对象名称),然后是经典的doc函数调用。


0
投票

@whyceewhite示例的@PaulBart1修复有点棘手,因为他替换声明的PI for 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

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