【问题标题】:What is the difference between class and instance methods?类方法和实例方法有什么区别?
【发布时间】:2010-11-06 10:02:07
【问题描述】:

类方法和实例方法有什么区别?

实例方法是访问器(getter 和 setter),而类方法几乎就是其他所有东西吗?

【问题讨论】:

    标签: objective-c oop methods class-method instance-methods


    【解决方案1】:

    实例方法适用于类的实例(即对象),而类方法适用于类本身。

    在 C# 中,类方法被标记为静态。未标记为静态的方法和属性是实例方法。

    class Foo {
      public static void ClassMethod() { ... }
      public void InstanceMethod() { ... }
    }
    

    【讨论】:

    • Argh - 抱歉,我刚刚注意到这是一个 Obj-C 问题。希望我的回答仍然适用,但请投票否决或投票删除。
    • 没有伤害。作为一般 OOP 原则,您答案的第一部分是正确的,它绝对适用于 Objective-C。如果您不想看到此类问题,可以将“objective-c”添加到您的标签列表中以忽略,尽管当然欢迎任何参与。 :-)
    【解决方案2】:

    Instances 方法对类的实例(即“对象”)进行操作。类方法与类相关联(大多数语言对这些人使用关键字static)。

    【讨论】:

      【解决方案3】:

      您的问题的答案并不特定于objective-c,但是在不同的语言中,类方法可能被称为静态方法。

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

      类方法

      • 对类变量进行操作(它们不能访问实例变量)
      • 不需要实例化对象即可应用
      • 有时可能是代码异味(一些不熟悉 OOP 的人将其用作在 OO 环境中进行结构化编程的拐杖)

      实例方法

      • 对实例变量和类变量进行操作
      • 必须有一个实例化的对象才能操作

      【讨论】:

      • 实例方法可以对类变量进行操作吗?
      【解决方案4】:

      就像大多数其他答案所说的那样,实例方法使用类的实例,而类方法可以仅与类名一起使用。在 Objective-C 中,它们是这样定义的:

      @interface MyClass : NSObject
      
      + (void)aClassMethod;
      - (void)anInstanceMethod;
      
      @end
      

      然后可以像这样使用它们:

      [MyClass aClassMethod];
      
      MyClass *object = [[MyClass alloc] init];
      [object anInstanceMethod];
      

      类方法的一些真实世界示例是许多 Foundation 类中的便捷方法,例如 NSString+stringWithFormat:NSArray+arrayWithArray:。实例方法是NSArray-count 方法。

      【讨论】:

      • 好答案。还值得注意的是,您将看到用于描述方法的特定速记符号。比如+[NSString stringWithFormat:]就是NSString上的类方法+stringWithFormat:; -[NSArray objectAtIndex:] 是一个实例方法。具有多个选择器部分的方法写成 -[NSMutableDictionary setObject:forKey:] 等。你会经常在 Cocoa 响应、文档和 Xcode 中看到这种表示法。
      • 我要补充一点,在许多其他语言中,类方法称为“静态”方法。为了回答最初的问题,访问器是实例方法,因为它们正在设置和获取特定实例的状态。在上面的示例中,NSArray count 返回特定实例中的对象数。
      • “而类方法可以仅与类名一起使用。”或类对象
      • 很抱歉让我兴奋……但我刚刚了解了其中的区别及其潜力。类方法摇滚,单例类也是如此!我已经坠入爱河了!
      • @BrianPan 静态方法和类方法不一样。它们相似,但它们命名不同的原因是它们的工作方式不同。例如,静态方法不能被覆盖。
      【解决方案5】:

      就像其他答案所说的那样,实例方法对对象进行操作并可以访问其实例变量,而类方法对整个类进行操作并且无法访问特定实例的变量(除非您传递实例in 作为参数)。

      类方法的一个很好的例子是计数器类型方法,它返回类实例的总数。类方法以+ 开头,而实例方法以- 开头。 例如:

      static int numberOfPeople = 0;
      
      @interface MNPerson : NSObject {
           int age;  //instance variable
      }
      
      + (int)population; //class method. Returns how many people have been made.
      - (id)init; //instance. Constructs object, increments numberOfPeople by one.
      - (int)age; //instance. returns the person age
      @end
      
      @implementation MNPerson
      - (id)init{
          if (self = [super init]){
                numberOfPeople++;
                age = 0;
          }    
          return self;
      }
      
      + (int)population{ 
           return numberOfPeople;
      }
      
      - (int)age{
           return age;
      }
      
      @end
      

      main.m:

      MNPerson *micmoo = [[MNPerson alloc] init];
      MNPerson *jon = [[MNPerson alloc] init];
      NSLog(@"Age: %d",[micmoo age]);
      NSLog(@"%Number Of people: %d",[MNPerson population]);
      

      输出: 年龄:0 人数:2人

      另一个例子是,如果您有一个希望用户能够调用的方法,有时将其设为类方法会很好。例如,如果您有一个名为 MathFunctions 的类,您可以这样做:

      + (int)square:(int)num{ 
            return num * num;
      }
      

      那么用户会调用:

      [MathFunctions square:34];
      

      无需实例化类!

      你也可以使用类函数来返回自动释放的对象,比如 NSArray 的

      + (NSArray *)arrayWithObject:(id)object
      

      这需要一个对象,将其放入数组中,然后返回数组的自动释放版本,该版本不必进行内存管理,非常适合临时数组等等。

      我希望你现在明白何时和/或为什么应该使用类方法!

      【讨论】:

      • micmoo,我建议你把“static int numberOfPeople = 0;”在代码格式的文本中?我很困惑,直到我在示例代码上方注意到它。除此之外,一个非常简洁的答案。
      • 请原谅我的新手困惑,但为什么你需要实例变量“age”和实例方法“age”?实例变量“age”的getter和setter不会用@synthetize创建吗?
      • @selytch "age" 必须被定义为一个属性才能使用 synthetize。
      【解决方案6】:

      类方法通常用于创建该类的实例

      例如,[NSString stringWithFormat:@"SomeParameter"]; 返回一个带有发送给它的参数的NSString 实例。因此,由于它是返回其类型对象的 Class 方法,因此也称为便捷方法。

      【讨论】:

        【解决方案7】:

        类方法不能改变或知道任何实例变量的值。这应该是判断实例方法是否可以是类方法的标准。

        【讨论】:

        • -1 来自我,因为您可以将实例传递给类方法,它将能够更改并知道它的变量值。
        【解决方案8】:

        以一个产生大量汽车的游戏为例。每辆汽车都属于 CCar 类。 当汽车被实例化时,它会调用

        [CCar registerCar:self]
        

        因此,CCar 类可以列出每个实例化的 CCar。 假设用户完成了一个关卡,并且想要移除所有汽车......您可以: 1- 浏览您手动创建的每个 CCar 的列表,然后执行 whicheverCar.remove(); 要么 2- 向 CCar 添加 removeAllCars 方法,当您调用 [CCar removeAllCars] 时,该方法会为您执行此操作。 IE。 allCars[n].remove();

        或者例如,您允许用户为整个应用程序指定默认字体大小,该字体大小在启动时加载和保存。 如果没有类方法,您可能必须执行类似

        的操作
        fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();
        

        使用类方法,您可以使用[FontHandler getDefaultFontSize]

        至于您的 removeVowels 函数,您会发现像 C# 这样的语言实际上都具有某些方法,例如 toLower 或 toUpper。

        例如myString.removeVowels()String.removeVowels(myString)(在 ObjC 中为 [String removeVowels:myString])。

        在这种情况下,实例可能会调用类方法,因此两者都可用。 即

        public function toLower():String{
          return String.toLower();
        }
        
        public static function toLower( String inString):String{
         //do stuff to string..
         return newString;
        }
        

        基本上,myString.toLower() 调用 [String toLower:ownValue]

        没有明确的答案,但如果您觉得将类方法推入会改进您的代码,请试一试,并记住类方法只会让您使用其他类方法/变量。

        【讨论】:

          【解决方案9】:

          还要记住,同样的想法也适用于变量。在谈论变量时,您会遇到静态、成员、实例、类等术语,就像谈论方法/函数一样。

          Obj-C 社区中的常用术语似乎是 ivar,例如变量,但我还不是 Obj-C 人。

          【讨论】:

            【解决方案10】:

            类方法

            是声明为静态的方法。无需创建类的实例即可调用该方法。类方法只能对类成员进行操作,而不能对实例成员进行操作,因为类方法不知道实例成员。类的实例方法也不能从类方法中调用,除非它们是在该类的实例上调用的。

            实例方法

            另一方面,需要类的实例存在才能调用它们,因此需要使用 new 关键字创建类的实例。实例方法对类的特定实例进行操作。实例方法未声明为静态。

            【讨论】:

            • 它也可以用“alloc”关键字创建,而不仅仅是“new”。另外,Objective-C不要求实例存在来调用实例方法,你可以向空指针发送消息。
            【解决方案11】:

            我认为理解这一点的最好方法是查看allocinit。正是这种解释让我理解了这些差异。

            类方法

            类方法作为一个整体应用于类。如果您检查alloc 方法,那是在方法声明之前由+ 表示的类方法。它是一个类方法,因为它被应用于类以创建该类的特定实例。

            实例方法

            您使用实例方法来修改类的特定实例,该实例对该实例是唯一的,而不是整个类。例如,init(在方法声明之前用- 表示)是一个实例方法,因为您通常在使用alloc 创建该类之后修改该类的属性。

            示例

            NSString *myString = [NSString alloc];
            

            您正在调用类方法alloc 以生成该类的实例。注意消息的接收者是一个类。

            [myString initWithFormat:@"Hope this answer helps someone"];
            

            您正在修改名为myStringNSString 实例,方法是在该实例上设置一些属性。注意消息的接收者是一个实例(NSString 类的对象)。

            【讨论】:

            • 检查“alloc”方法是什么意思?您能指出我在文档中的特定位置吗? (编辑)--> 啊,没关系,是的,在 NSObject 文档中它说在“任务”下 - developer.apple.com/library/ios/documentation/cocoa/reference/…
            • 您并不需要真正了解它的真正作用来掌握这一点,只需将它应用于类即可。简单地说:alloc 为对象分配足够的内存,init 将修改这些内存地址中的内容以定义对象的状态。除非有空间可以修改对象,否则我们无法修改对象,因此我们在决定给我们该空间的类上使用alloc
            【解决方案12】:

            对上述答案的更新,我同意实例方法使用类的实例,而类方法可以仅与类名一起使用。

            在Objective-C中自动引用计数出现后,实例方法和类方法之间没有任何区别了。

            例如[NS StringWithformat:..]一个类方法和[[NSString alloc] initwihtformat:..]一个实例方法,在ARC之后都是一样的

            【讨论】:

              【解决方案13】:

              所有技术细节都已在其他答案中很好地涵盖。我只想分享一个简单的类比,我认为它很好地说明了类和实例之间的区别:

              就像房子的蓝图:你只有一个蓝图,而且(通常)光靠蓝图做不了那么多。 p>

              instance(或 object)是您根据蓝图建造的实际 house:您可以从相同的蓝图。然后,您可以为每个房屋的墙壁涂上不同的颜色,就像您可以独立更改类的每个实例的属性而不影响其他实例一样。

              【讨论】:

              • @JohannesFahrenkrug 在这里很好地解释了类和对象的概念。实际问题不是针对difference between class method and an instance method
              • 类与类实例的完美解释。类对新手来说是一个奇怪的概念,这从根本上解释了它。
              • @JohannesFahrenkrug 真的是一个很好的解释,这让我想到了两者的区别以及何时使用两者
              • 这么棒的解释:)
              • 很好的比喻。请有人给这家伙一年供应的比萨饼。
              【解决方案14】:

              如果我理解正确的话。

              class 方法不需要您分配该对象的实例来使用/处理它。 class 方法是自包含的,并且可以在不依赖于该类的任何对象的状态的情况下运行。 class 方法应该为其自己的所有工作分配内存并在完成后释放,因为该类的任何实例都无法释放在之前调用该类方法时分配的任何内存。

              instance 方法正好相反。除非您分配该类的实例,否则您不能调用它。它就像一个普通的类,有一个构造函数,可以有一个析构函数(清理所有分配的内存)。

              大多数情况下(除非您正在编写可重用的库,否则您不需要class 变量。

              【讨论】:

              • 需要类方法的一个明显情况是创建实例。您必须能够在没有任何实例的情况下创建实例,否则永远无法创建第一个实例。这就是为什么 +alloc 是并且必须是类方法的原因。
              【解决方案15】:

              在 Objective-C 中,所有方法都以“-”或“+”字符开头。 示例:

              @interface MyClass : NSObject
              // instance method
              - (void) instanceMethod;
              
              + (void) classMethod;
              @end
              

              “+”和“-”字符分别指定方法是class method 还是instance method

              如果我们调用这些方法,区别就会很明显。这里的方法是在MyClass 中声明的。

              instance method 需要一个类的实例:

              MyClass* myClass = [[MyClass alloc] init];
              [myClass instanceMethod];
              

              MyClass内部的其他方法可以使用self调用MyClass的实例方法:

              -(void) someMethod
              {
                  [self instanceMethod];
              }
              

              但是,class methods 必须在类本身上调用:

              [MyClass classMethod];
              

              或者:

              MyClass* myClass = [[MyClass alloc] init];
              [myClass class] classMethod];
              

              这行不通:

              // Error
              [myClass classMethod];
              // Error
              [self classMethod];
              

              【讨论】:

                【解决方案16】:

                类方法


                类方法通常要么创建类的新实例,要么检索类的一些全局属性。类方法不对实例进行操作,也不能访问实例变量。


                实例方法


                实例方法对类的特定实例进行操作。例如,您实现的访问器方法都是实例方法。您可以使用它们来设置或获取特定对象的实例变量。


                调用


                要调用实例方法,请将消息发送到类的实例。

                要调用类方法,请直接将消息发送到类。


                来源:IOS - Objective-C - Class Methods And Instance Methods

                【讨论】:

                  【解决方案17】:

                  注意:这只是伪代码格式

                  类方法

                  几乎所有它需要做的就是在编译时。它不需要任何用户输入,它的计算也不基于实例。关于它的一切都基于类/蓝图——这是独一无二的,即你没有一个类的多个蓝图。在编译期间你能有不同的变化吗?不,因此该类是唯一的,因此无论您调用类方法多少次,指向它的指针都是相同的。

                  PlanetOfLiving: return @"Earth" // No matter how many times you run this method...nothing changes.
                  

                  实例方法

                  相反,实例方法发生在运行时,因为只有在你才创建了一个实例,该实例在每次实例化时都会有所不同。

                  initWithName: @"John" lastName: @"Doe"Age:12 @"cool"
                  initWithName: @"Donald" lastName: @"Drumpf"Age:5 attitude:@"He started"
                  initWithName: @"President" lastName: @"Obama"Age:54 attitude: @"Awesome"
                  //As you can see the value can change for each instance.
                  

                  如果您来自其他语言 静态方法与类方法相同。
                  如果你来自 Swift,类型方法和类方法是一样的。

                  【讨论】:

                    【解决方案18】:

                    补充以上答案

                    类方法将适用于类,我们将其用于一般用途,例如 +stringWithFormat、类的大小,最重要的是用于 init 等

                    NSString *str = [NSString stringWithFormat:@"%.02f%%",someFloat]; 
                    

                    Instance Method 将作用于一个类的实例而不是一个类的实例,就像我们有两个人一样,我们想知道每个人的平衡,这里我们需要使用实例方法。因为它不会返回一般响应。例如比如确定 NSSArray 的计数等。

                    [johnson getAccountBalance];
                    [ankit getAccountBalance];
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2015-04-18
                      • 1970-01-01
                      • 2013-06-12
                      • 1970-01-01
                      • 2012-10-21
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-12-13
                      相关资源
                      最近更新 更多