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

Posted

技术标签:

【中文标题】类型方法和类型实例方法等之间的区别?【英文标题】:Difference between type method and type instance method, etc? 【发布时间】:2015-12-11 00:43:38 【问题描述】:

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

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

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

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

    最后,swift中是否存在类属性?

很抱歉给您带来了困惑:'(

【问题讨论】:

【参考方案1】:

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

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

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

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

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

let areaOfMyCircleInstance = myCircleInstance.area()

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

例如:

Circle.printTypeName()

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

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

参见上面的解释。

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

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

在我的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 属性是类属性的示例。

参考资料:

Swift Language Reference - Types Swift Language Reference - Properties Swift Language Reference - Methods

【讨论】:

【参考方案2】:

不同之处在于为每个实例创建实例方法和属性。为整个类型创建类型方法和属性

假设你有 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 是类型属性或静态属性。它们只创建一次,并且对于每个实例和每个其他对象都具有相同的值。 您可以通过引用“类型”(在我们的例子中为结构)Employee.NAME 来访问类型属性

类型方法类似于类型(结构、类、枚举)的全局函数。它们通常用于封装绑定到类型但可能不需要实例的功能。与示例中一样,类型方法 getNameOfField(index:Int) -> String 根据索引返回字段名称。要返回此信息,您不必创建 Employee 的实例

类型是结构、类和枚举

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

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

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

【讨论】:

好兄弟,非常感谢!但是变异的东西让我很困惑......那是什么?它有什么作用? 结构实例是不可变的。一旦创建,您将无法更改实例。将方法定义为 mutating 允许它对实例进行更改【参考方案3】:

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

【讨论】:

【参考方案4】:

这都是关于范围的,它定义了在哪里以及如何使用函数的边界。只有在从类中初始化对象后才能使用方法。简单来说,要使用方法,必须先创建对象,方法属于对象。

但是,如果您需要使用方法但不需要启动对象,例如全局设置(例如 CLLocationManager 中的 authorizationStatus() 函数,该怎么办?对于 GPS 坐标授权),然后您可以创建一个类型方法,只需引用 type 名称(NOT 对象名称),然后调用经典的 doc 函数。

【讨论】:

【参考方案5】:

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

 //

【讨论】:

以上是关于类型方法和类型实例方法等之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

golang 方法

Java中构造方法实例方法类方法的区别

Java中构造方法实例方法类方法的区别

go语言方法实例

命名空间,类,对象和实例之间有什么区别?

C# 如何根据指定变量来实例化对象?