对象和实例之间的区别


82

我知道以前曾提出 这样的问题,但是我仍然觉得答案太模糊了,我(而且,从某种意义上说,是某些/大多数初学者)很难理解。

我一直在尝试自学比程序和基本OOP更广泛的编程概念。我了解OOP的具体概念(您创建一个具有数据(成员)和函数(方法)的类,然后在运行时实例化该类以实际执行此类操作。

我认为我对类的含义有所了解(某种实例的设计蓝图,该实例在编译时以其相似性创建)。但是如果是这样,什么是物体?我也知道,在基于原型的语言中,这甚至可以使事情变得更糟,但这也许就是为什么在我的脑海中需要对对象和实例进行清楚的区分。

除此之外,我还与“对象”和“实例”的概念作斗争。我阅读的许多资源(包括SO的答案)都说它们基本相同,而语义上却有所不同。别人说这两者之间存在真正的概念差异。

SO的专家可以帮助初学者在OOP领域中迈出“啊哈”的时刻吗?

注意:这不是家庭作业,我不上学-但是,我认为这会对寻求家庭作业帮助的人有所帮助。


1
我想知道您是否要添加一些其他问题,例如“是否所有实例对象?” ,以及“是否所有对象实例?” 如果两个都“是”,那么我们可以确认它们是相同的。
WesternGun

一旦实例化了一个类(使用new),该实例化的对象便成为对象。对象是可以遵循封装,多态性,面向对象编程的抽象原理以及与程序进行交互以消耗类中定义的实例成员的真实对象的东西。对象包含实例成员(非静态成员)。因此,类的实例是一个对象。当您指代出生地的起源时,会使用“实例”一词,如果您说“一个类的实例”,则比“一个类的对象”更清楚
p_champ

Answers:


129

房屋设计的蓝图就像一个班级描述。根据该蓝图建造的所有房屋均为该类别的对象。给定的房子是一个实例。


6
另外,有一条我家乡的街道在当地颇有名气,因为一排有八座同样建造的砖砌房屋(在“住房开发”概念出现之前)。因此,我可以很好地将其形象化。“类”是建筑师提出的。成品房屋是“对象”,因为它们的建造方式完全相同。每个房子是一个“实例”,因为他们有(和可以继续),因为那么所有的区别对待[现在一个人站在一边:O(]
TCCV

16
静态方法就像所有房屋共享的实用程序。
WOPR

2
但是,根据蓝图建造的房屋不是实例吗?
Hot Licks

1
这意味着,类定义所占据的第一个内存是实例。而所有创建的对象都称为对象。
哈菲兹·谢赫巴兹·阿里

6
对象和实例不完全相同吗?
Praveen Kumar 2015年

42

事实是,面向对象的编程通常会通过在开发的哲学方面与计算机的实际机械工作之间建立脱节而造成混乱。我将尝试为您对比两者:

OOP的基本概念是:类>>对象>>实例。

类别=蓝图。对象是基于“蓝图”(如房屋)建造的实际事物。实例是对象的虚拟副本(而不是真实副本)。

“实例”的更多技术解释是它是“内存引用”或引用变量。这意味着“实例”是内存中有一个对象的内存地址。它处理的对象与实例被称为“实例”的对象相同。如果您有一个对象的许多实例,则实际上您的内存中的不同位置实际上有很多变量,它们都具有相同的确切内存地址-都是相同的确切对象的地址。尽管看起来好像可以在代码中进行更改,但是您永远无法“更改”实例。当您“更改”实例时,您真正要做的就是直接更改原始对象。在电子上,处理器在更改原始对象的数据之前会先经过内存中的一个额外位置(参考变量/实例)。

过程是:处理器>>实例的内存位置>>原始对象的内存位置。

请注意,使用哪个实例都没有关系-最终结果将始终相同。所有实例将继续在其内存位置(对象的内存地址)中保留相同的确切信息,只有对象会更改。

类和对象之间的关系有些混乱,尽管从哲学上讲它是最容易理解的(蓝图>>房子)。如果对象是保存在内存中某处的实际数据,那么“类”是什么?事实证明,从机械上讲,该对象是该类的精确副本。因此,该类只是内存中其他地方的另一个变量,它拥有与对象相同的确切信息。注意关系之间的区别:

对象是类的副本。实例是保存对象的内存地址的变量。

您也可以具有相同类的多个对象,然后每个对象具有多个实例。在这些情况下,每个对象的实例集的值相等,但是对象之间的实例不相等。例如:

让A类从A类让Object1,Object2和Object3。

// Object1的确切值与object2和object3相同,但是它们在内存中的位置不同。

来自Object1 >>让obj1_Instance1,obj1_Instace2,obj1_Instance3

//所有这些实例的值也相等,并且在内存中的不同位置。它们的值= Object1.MemoryAddress。

等等

当您开始引入类型时,事情会变得更加混乱。这是一个使用c#中的类型的示例:

//假设类Person存在Person john = new Person();

实际上,如果将代码分为两部分,则更易于分析:

Person john;
john = new Person();

用技术术语来说,第一行“声明了一个类型变量人。但是,这是什么意思??一般的解释是,我现在有一个只能容纳一个Person对象的空变量。但是请稍等-它是一个空变量!该变量的存储位置中没有任何内容。事实证明,“类型”在机械上是没有意义的。类型最初是作为管理数据的一种方式发明的。即使您声明基本类型,例如int,str,chr(不进行初始化),计算机内也不会发生任何事情。程序设计的这种怪异的语法方面是人们理解类是对象的蓝图的一部分。OOP对带有委托类型,事件处理程序等的类型变得更加困惑。我不会尝试过多地关注它们,而只是记住它们都是用词不当。

第二行也有点混乱,因为它同时执行两项操作:

首先评估右侧的“ new Person()”。它创建了Person类的新副本-即,它创​​建了一个新对象。

然后在左侧评估“ john =“”。它将john变成一个引用变量,为它提供刚在同一行右侧创建的对象的内存地址。

如果您想成为一名优秀的开发人员,那么一定要理解,没有任何计算机环境能够基于哲学理想而工作,这一点很重要。计算机甚至没有那么逻辑-它们实际上只是一大堆电线,这些电线使用基本的布尔电路(主要是NAND和OR)粘合在一起。


32

类别”一词来自“分类”类别放入其中的“类别”),现在我们都听说“类别”就像一张蓝图,但这到底是什么意思?这意味着该类具有特定类别的描述,(我想用Java来举例说明类,对象和实例之间的区别,并且我希望读者在阅读它时像一个故事一样可视化它,如果您不熟悉Java没关系)因此让我们首先创建一个名为HumanBeing类别,这样Java程序将如下表示。

class HumanBeing{ 
   /*We will slowly build this category*/ 
}

现在,HumanBeing拥有什么属性,一般名称年龄身高体重,现在让我们将自身限制为这四个属性,然后将其添加到类别中

class HumanBeing{
    private String Name;
    private int Age;
    private float Height;
    private float Weight; 

   /*We still need to add methods*/

}

现在,每个类别都有一个行为,例如类别Dog的行为是吠叫,抓取,滚动等。类似地,我们的类别HumanBeing也可以具有某些行为,例如,当我们问问HumanBeing时,您的名字/年龄/体重/高度?它应该给我们它的名字/年龄/体重/身高,所以在java中我们这样做

class HumanBeing{
    private String Name;
    private int Age;
    private float Height;
    private float Weight;  

    public HumanBeing(String Name,int Age,float Height,float Weight){
       this.Name = Name;
       this.Age  = Age;
       this.Height = Height;
       this.Weight = Weight;
    }

    public String getName(){
      return this.Name;
    }

    public int getAge(){
      return this.age;
    }

    public float getHeight(){
      return this.Height;
    }

    public float getWeight(){
      return this.Weight;
    }
}

现在,我们将行为添加到了HumanBeing类别中,因此我们可以询问其名称,年龄,身高,体重,但是您可以从谁那里询问这些详细信息,因为class HumanBeing这只是一个类别,它是一个蓝图,例如,建筑师为他要建造的建筑物的文件,现在我们不能继续在蓝图(对建筑物的描述)中居住,我们只能在建筑物建成后居住在建筑物中,因此在这里我们需要从我们的类别中创建人上面已经描述过了,那么我们该如何在Java中做到这一点呢?

class Birth{
  public static void main(String [] args){
    HumanBeing firstHuman = new HumanBeing("Adam",25,6.2,90);    
  }
}

现在在上面的示例中,我们创建了第一个名称为age height weight的人,那么上面的代码中到底发生了什么?。我们正在实例化类别HumanBeing,即创建了该类的对象

注意: 对象和实例不是同义词在某些情况下,对象和实例似乎是同义词,但它们不是同义词,我将同时给出两种情况

案例1:对象和背景似乎是同义词
让我解释一下,当我们说HumanBeing firstHuman = new HumanBeing("Adam",25,6.2,90); 一个对象我们的类是在创建堆内存和一些地址分配给它,并firstHuman持有到该地址的引用,现在这个对象是人的对象也是人的实例。在这里,看来对象和实例是同义词,我再说一遍它们不是同义词

让我们恢复我们的故事,我们创建了第一个人类,现在我们可以问他的名字,年龄,身高,体重,这就是我们在Java中的做法

class Birth{
  public static void main(String [] args){
    HumanBeing firstHuman = new HumanBeing("Adam",25,6.2,90);
    System.out.println(firstHuman.getName());
    System.out.println(firstHuman.getAge());
    ...
    ...  
  }
}

因此,我们拥有第一个人类并通过赋予我们的第一个人类一定的资格来移动羽毛,让我们让他成为医生,因此我们需要一个名为Doctor的类别并赋予我们的Doctor一些行为,因此在Java中,我们执行以下操作

class Doctor extends HumanBeing{
   public Doctor(String Name,int Age,float Height,float Weight){
      super(Name,Age,Height,Weight);
   }
   public void doOperation(){
    /* Do some Operation*/ 
   }

   public void doConsultation(){
    /* Do so Consultation*/
   }
}  

在这里,我们使用了继承的概念,它在代码中带来了一定的可重用性,每个Doctor永远都是HumanBeing的第一人,因此Doctor的Name,Age,Weight,Height将从HumanBeing继承而来,而无需再次编写,请注意,我们只是写了一份尚未创建医生的说明,所以让我们在我们的医生中创建一名医生。class Birth

class Birth{
  public static void main(String [] args){
    Doctor firstDoctor = new Doctor("Strange",40,6,80);
    .......
    .......
    /*Assume some method calls , use of behaviour*/
    .......
    .......    
  }
}

情况2:对象和实例不是同义词
在上面的代码中,我们可以直观地看到我们正在实例化Doctor类并将其变为现实,即我们只是创建了Doctor类Object,因为我们已经知道Object是在堆内存上创建的firstDoctor在堆上保存对该Object的引用;

这个特定的对象firstDoctor如下(请注意,firstDoctor持有对象的引用,不是对象本身)

  1. firstDoctorA的对象class DoctorA的实例class Doctor
  2. firstDoctor的不是对象class HumanBeing,但一个实例的class HumanBeing

因此,特定对象可以是特定类的实例,但不必是该给定类的对象

结论:

如果对象满足特定类别的所有特征,则称该对象为该特定类别的实例。

现实世界的例子如下,我们最初是人类,因此将我们形象化为人类的对象,现在,当我们长大后,我们承担起责任,学习新技能,并在生活中扮演不同的角色。 ,母亲现在我们到底是什么?我们可以说我们是人类的对象,但兄弟,女儿等的实例

我希望这有帮助

谢谢


5
...为什么我们在这个答案上只有3个投票?
Pratik Ambani

13

在此处输入图片说明

对象是内存中的事物,而实例是引用它们的事物。在上图中:

  • std(instance)-> Student Object(右侧)
  • std1(实例)->学生对象(左)
  • std2(实例)->学生对象(左)
  • std3(instance)->没有对象(空)

4
太棒了。我真的很喜欢它的水平很低的事实。我正在反复研究我是否比类比更好。我认为一起了解2是我真正需要的。支持,但不确定是否可以给您答案,因为已经将答案提供给了乔。不过谢谢你 这清除了很多。
TCCV

那么,实例是指向对象的指针吗?(实例==随内存地址变化吗?)
Stano,

6
Truong,您的回答是错误和令人困惑的。实际上,实例是从基类对象派生的对象。实例==对象。这个这个答案例如很好地解释了这个术语。
Stano

@jww:该图像是指向math.hws.edu/javanotes/c5/objectsInHeap.png的链接,该链接现在为404。大概在发布时可见。
马特·伯兰

6

对象是类的实例(对于基于类的语言)。

我认为这是我能想到的最简单的解释。


1
我同意您的解释与我的阅读方式有关,但是在线上有很多条目可以区分这两者。我不知道在没有语言的情况下是否无法回答此类问题(哇,是个元问题,这个问题是一个无法使用语言实例化的类,大声笑)。
TCCV 2010年

6

一个类定义一个对象。您甚至可以使用多种语言进行进一步介绍,说接口定义了对象之间的通用属性和方法。

对象是可以代表现实世界中某些事物的事物。当您希望对象实际代表现实世界中的某物时,必须实例化该对象。实例化意味着您必须通常通过构造函数来定义此特定对象的特征(属性)。

定义了这些特征后,便有了对象的实例。

希望这可以清除一切。


我认为这基本上是说乔的话。如果我错了纠正我。
TCCV 2010年

3
乔上面说,所有根据蓝图建造的房屋都是物体。真正。他说,给定的房子就是一个实例。真正。但是,所有房屋都是实例,给定房屋也是对象。在没有的地方,他正在有所作为。在代码中,在构造对象和实例时,有必要在对象和实例之间进行区分。我们说它是在实际构建时实例化的。一个常见的问题可能是:您还记得实例化该对象吗?即。如果在声明对象后忘记调用构造函数。
德里克·里兹

1
啊,这是一个很好的区别。换句话说,实例是已构造的对象(即,调用了构造函数的对象)。
TCCV

3

“类描述了一组称为其实例的对象。” -施乐学习研究小组,“ Smalltalk-80系统”,字节杂志第06卷第08期,第39页,1981年。


2

什么是对象?

对象是类的实例。通过找到您周围的真实示例,可以最好地理解物体。您的办公桌,笔记本电脑,汽车都是真实的物体实例。

现实世界中的对象共有两个特征,它们都有状态和行为。人类也是物体的一个很好的例子,人类具有状态/属性-名称,身高,体重和行为-走路,奔跑,说话,睡觉,编码:P。

什么是班级?

类是描述对象详细信息的蓝图或模板。这些细节就是

名称属性/状态操作/方法

class Car 
{
    int speed = 0;
    int gear = 1;

    void changeGear(int newGear)
    {
        gear = newGear;
    }

    void speedUp(int increment) 
    {
        speed = speed + increment;
    }

    void applyBrakes(int decrement) 
    {
        speed = speed - decrement;
    }
}

考虑上面的示例,这些字段speedgear将代表对象的状态,方法changeGearspeedUpapplyBrakes定义Car对象与外界的行为。

参考文献:


1

我认为必须指出,通常有两件事很重要。蓝图和副本。人们倾向于命名这些不同的事物。类,对象,实例只是人们为其使用的一些名称。重要的是,存在蓝图及其副本-无论其名称如何。如果您已经对这两个方面有所了解,请避免使您感到困惑的其他事情。


0

让我们将苹果与苹果进行比较。我们都知道苹果是什么。看起来像什么。它的味道如何。那是一堂课。这是事物的定义。这是我们对某件事的了解。

现在去找一个苹果。那是一个实例。我们可以看到它。我们可以品尝。我们可以用它做事。这就是我们所拥有的。

课堂=我们对某件事的了解。一个定义。

对象/实例=符合我们现有定义并可以执行操作的事物。


0

在某些情况下,术语“对象”可用于描述实例,但在其他情况下,其用于描述实例的引用。术语“实例”仅指实际实例。

例如,列表可以描述为对象的集合,但是列表实际上持有的是对对象实例的引用。


因此,在这种情况下,引用只是一个占位符,其中包含实例的链接?链接可能在哪里,例如内存地址?
TCCV 2010年

0

我一直喜欢将类的定义等同于“抽象数据类型”的想法。就是说,当您定义一个类时,您正在定义一种新的“东西”,它的数据类型表示形式(以基元和其他“东西”形式)以及他的行为(以功能和/或方法形式)。(抱歉,普遍性和形式主义)

每当您定义一个类时,您就为定义带有其属性和行为的某些实体打开了一种新的可能性,当您从中实例化和/或创建一个特定的对象时,您实际上正在实现这种可能性。

有时,术语“对象”和“实例”可以互换。一些OOP纯粹主义者将坚持一切都是对象,我不会抱怨,但是在真实的OOP世界中,我们开发人员使用两个概念:

  1. 类:抽象数据类型示例,您可以从中获取其他ADT并创建对象。
  2. 对象:也称为实例,表示由给定的抽象数据类型表示的数据结构和功能的特定示例。

0

面向对象编程是一个系统隐喻,可以帮助您整理程序需要处理的知识,从而使开发程序更容易。当您选择使用OOP进行编程时,您会选择OOP-Google,并决定通过发送消息来看到现实世界中的问题,因为许多对象之间相互协作。而不是看到一个盖伊驾驶汽车,而是看到一个盖伊向汽车发送一条消息,指出他想要汽车做什么。汽车是一个大对象,它将通过向汽车的引擎或车轮发送信息来响应该信息,以便能够正确响应驾驶员在信息中告诉他的操作,等等。

创建系统隐喻后,将所有现实视为发送消息的对象,您决定将与您的问题域相关的所有事物放入PC。在这里,您会注意到有很多家伙在驱动不同的卡,并且对每个卡的行为分别进行编程是没有意义的,因为它们的行为方式都相同……所以您可以说两点:

  • 所有这些人的行为都相同,因此,我将创建一个名为Driver的类,该类将指定世界上所有Drivers的行为人,因为他们的行为均相同。(并且您正在使用基于类的OOP)
  • 或者您可以说嘿!第二个驱动程序的行为与第一个驱动程序的行为相同,只不过他喜欢快一点。第三位驾驶员的行为方式与第一位驾驶员相同,只是他喜欢在驾驶时曲折行驶。(并且您使用基于原型的OOP)。

然后,您开始将所有驱动程序的行为(或第一个驱动程序的行为以及第二个和第三个驱动程序与该驱动程序有何不同)的信息放入计算机,并在一段时间后有了程序,并使用代码创建三个驱动程序,它们是您在该PC上使用的模型,以符合您在现实世界中看到的驱动程序。您在PC内创建的这3个驱动程序是原型的实例(实际上第一个是原型,根据您对事物的建模方式,第一个可能是原型本人)或您创建的类的实例。实例和对象之间的区别在于,对象是您在现实世界中使用的隐喻。您选择将人和汽车视为对象(将它们视为实例)是彼此协作的。然后,您可以将其用作创建代码的灵感。创建原型或类之后,该实例仅存在于您的程序中。“对象”存在于PC外部,因为您使用其映射将真实世界与程序结合在一起。它将Guy与您在PC中创建的Driver实例结合在一起。因此,对象和实例是极为相关的,但是它们并不完全相同(实例是程序中对象的“腿”,而另一个“腿”在现实世界中)。


0

我想最好的答案已经给出了。

类是蓝图,对象是建筑物,或者该蓝图的示例也对我有用。

有时,我想认为类是模板(例如在MS Word中),而对象是使用模板的文档。


0

扩展该线程中先前给出的示例之一...

考虑一种情况-要求在附近的居民区中建造5栋房屋。所有5栋房屋都具有相同的建筑结构。建筑结构是一。房子是一个对象。每个住着人的房子都是一个实例

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.