31

我开始学习 OOP,我想了解什么是类。我对某些核心元素的使用松散程度感到有些困惑,从而增加了我的困惑。

我看过 C++ 类,java 类,我想知道足够的知识来编写我自己的伪类来帮助我理解。

例如,在这篇文章中,我读到了这个(.. 类属性(或类属性、字段或数据成员)

我已经看到了一些很好的问题,这些问题表明类属性和类字段之间存在差异,例如C# 中的字段和属性之间有什么区别?

根据我正在学习的语言,是

  • 财产
  • 字段
  • 类变量
  • 属性

因语言而异?

4

7 回答 7

32

“字段”、“类变量”和“属性”或多或少是相同的——附加到对象的低级存储槽。每种语言的文档可能始终使用不同的术语,但大多数实际程序员可以互换使用它们。(但是,这也意味着某些术语可能是模棱两可的,例如“类变量” - 它可以解释为“给定类的实例的变量”,或“类对象本身的变量”其中类对象是您可以直接操作的东西。)

在我使用的大多数语言中,“属性”是完全不同的东西——它们是一种将自定义行为附加到读/写字段的方法。(或更换它。)

所以在 Java 中,典型的例子是:

class Circle {

    // The radius field
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }

    // The radius property
    public double getRadius() {
        return radius;
    }
    public void setRadius(double radius) {
        // We're doing something else besides setting the field value in the 
        // property setter
        System.out.println("Setting radius to " + radius);
        this.radius = radius;
    }

    // The circumference property, which is read-only
    public double getCircumference() {
        // We're not even reading a field here.
        return 2 * Math.PI * radius;
    }

}

(请注意,在 Java 中,属性foo是一对被调用的访问器方法getFoo()-setFoo()或者如果属性是只读的,则只是 getter。)


另一种看待这一点的方式是,“属性”是一种抽象——对象承诺允许调用者获取或设置一段数据。而“字段”等是这种抽象的一种可能实现。上面例子中的值getRadius()可以getCircumference()直接存储,也可以计算出来,调用者无所谓;setter 可能有也可能没有副作用;呼叫者无关紧要。

于 2013-05-25T15:54:53.103 回答
10

我同意你的看法,由于许多 OO 术语的定义松散和使用不一致,有很多不必要的混淆。您所询问的术语在某种程度上可以互换使用,但可以说有些术语比其他术语更通用(降序):属性-> 属性-> 类变量-> 字段。

以下段落摘自Grady Booch的“面向对象的分析与设计”,有助于阐明该主题。首先,了解状态的概念很重要:

对象的状态包括对象的所有(通常是静态的)属性加上每个属性的当前(通常是动态的)值。属性是指对象的属性和与其他对象的关系的总和。

OOP 在某些命名法方面非常通用,因为它因语言而异:

术语字段(Object Pascal)、实例变量(Smalltalk)、成员对象 (C++) 和插槽 (CLOS) 是可互换的,表示对象部分状态的存储库。它们共同构成了对象的结构。

但作者介绍的符号是准确的:

属性表示聚合对象的一部分,因此在分析和设计期间用于表示类的单一属性。使用与语言无关的语法,一个属性可以有一个名称、一个类,或两者兼有,还可以有一个默认表达式:A:C=E.

类变量:类状态的一部分。一个类的类变量共同构成了它的结构。类变量由同一类的所有实例共享。在 C++ 中,类变量被声明为静态成员。

总之:

  • 属性是一个广泛的概念,用于表示一个类的特定特征,包括它的属性以及它与其他类的关系。

  • 属性 表示聚合对象的一部分,因此在分析和设计期间用于表示类的单一属性。

  • 类变量在一个存在单个副本的类中定义的属性,无论该类的实例存在多少。所以该类的所有实例共享它的值以及它的声明。

  • 字段实例变量的语言特定术语,即其值特定于每个对象的属性

于 2016-06-16T03:46:36.230 回答
2

我从事 oop 已有 20 多年了,我发现人们经常对相同的事情使用不同的词。我的理解是字段、类变量和属性都意味着同样的事情。但是,您在问题中包含的 stackoverflow 链接最好地描述了属性。

于 2013-05-25T15:55:43.110 回答
1

通常,字段、方法、静态方法、属性、属性和类(或静态变量)不会因语言而改变......虽然语法可能会因每种语言而改变,但它们会以您期望的方式发挥作用跨语言(期望字段/数据成员等术语可以跨语言互换使用)

在 C# 中......

字段是存在于给定类实例的变量。

例如。

public class BaseClass
{
    // This is a field that might be different in each instance of a class
    private int _field; 

    // This is a property that accesses a field
    protected int GetField
    {
        get
        {
            return _field;
        }
    }
}

字段具有“可见性”,这决定了其他类可以看到该字段,因此在上面的示例中,私有字段只能由包含它的类使用,但属性访问器提供子类对该字段的只读访问。

属性可以让您获取(有时称为访问器)或设置(有时称为 mutator)字段的值...属性让您可以做一些事情,例如防止从类外部写入字段,更改字段(例如私有/受保护/公共)。mutator 允许您在设置字段的值之前提供一些自定义逻辑

所以属性更像是获取/设置字段值的方法,但提供更多功能

例如。

public class BaseClass
{
    // This is a field that might be different in each instance of a class
    private int _field; 

    // This is a property that accesses a field, but since it's visibility 
    // is protected only subclasses will know about this property 
    // (and through it the field) - The field and property in this case
    // will be hidden from other classes.
    protected int GetField
    {
        // This is an accessor
        get
        {
            return _field;
        }
        // This is a mutator
        set
        {
            // This can perform some more logic
            if (_field != value) 
            {
                 Console.WriteLine("The value of _field changed");
                 _field = value;
                 OnChanged; // Call some imaginary OnChange method
            } else {
                 Console.WriteLine("The value of _field was not changed");
            }
        }
    }
}

类或静态变量是类的所有实例都相同的变量。因此,例如,如果您想要一个类的描述,则该描述对于该类的所有实例都是相同的,并且可以通过以下方式访问使用类,例如。

public class BaseClass
{
    // A static (or class variable) can be accessed from anywhere by writing
    // BaseClass.DESCRIPTION
    public static string DESCRIPTION = "BaseClass";
}

public class TestClass
{
    public void Test()
    {
        string BaseClassDescription = BaseClass.DESCRIPTION;
    }
}

在使用与属性相关的术语时,我会小心。在 C# 中,它是一个可以通过“装饰”类或方法来应用于其他类或方法的类,在其他上下文中,它可能只是指一个类包含的字段。

// The functionality of this attribute will be documented somewhere
[Test]
public class TestClass
{
    [TestMethod]
    public void TestMethod()
    {
    }
}

有些语言没有像 C# 那样的“属性”(见上文)

希望这一切都有意义......不想让你超载!

于 2013-05-25T16:29:16.807 回答
1

首先,您需要选择一种语言。例如,我建议您选择 Ruby 语言和社区。在您选择一种语言之前,您无法避免混淆,因为不同的社区对相同的事物使用不同的术语。

例如,Module在 Ruby 中称为抽象类,Java 称为抽象类。在某些语言中称为属性instance variables,在 Ruby 中称为属性。我特别推荐 Ruby,因为它具有逻辑性和设计良好的 OOP 系统。

在 *.rb 文件或irb(交互式 Ruby 解释器)的命令行中写入以下内容:

class Dog                         # <-- Here you define a class representing all dogs.
  def breathe                     # <-- Here you teach your class a method: #breathe
    puts "I'm breathing."
  end

  def speak                       # <-- Here you teach your class another method: #speak
    puts "Bow wow!"
  end
end

现在你有了一个类,你可以创建它的一个实例

Seamus = Dog.new

您刚刚创建了一个实例,即 Dog 类的特定狗,并将其存储在常量 中Seamus。现在你可以玩它了:

Seamus.breathe                   # <-- Invoking #breathe instance method of Seamus
#=> I'm breathing.
Seamus.speak                     # <-- Invoking #speak instance method of Seamus
#=> Bow wow!

至于您剩下的术语问题,“属性”或“属性”在 Ruby 中被理解为“变量”,几乎总是一个实例变量。至于“数据成员”这个词,就别管它了。术语“字段”在 Ruby 中并没有真正使用,而“类变量”在 Ruby 中意味着很少使用的东西,你现在绝对不需要知道。

因此,为了让世界保持美好并向您展示 OOP 在 Ruby 中非常简单和轻松,让我们创建一个属性,或者用 Ruby 术语来说,是一个Dog类的实例变量。众所周知,每只狗都有一定的体重,不同的狗可能有不同的体重。因此,在创建新狗时,我们将要求用户告诉我们狗的重量:

class Dog
  def initialize( weight )  # <-- Defining initialization method with one argument 'weight'
    @weight = weight        # <-- Setting the dog's attribute (instance variable)
  end
  attr_reader :weight       # <-- Making the dog's weight attribute visible to the world.
end

Drooly = Dog.new( 16 )      # <-- Weight now must provide weight upon initialization.
Drooly.weight               # <-- Now we can ask Drooly about his weight.
#=> 16

请记住,使用 Ruby(或 Python),事情很简单。

于 2013-05-25T21:28:30.967 回答
1

我在我的问题中发现.Net 中定义的属性只是代码的一种方便语法,它们根本不依赖于底层变量(当然,自动实现的属性除外)。因此,说“类属性和类字段之间有什么区别”就像说:方法和属性之间有什么区别。没有区别,一个是代码,一个是数据。而且,它们之间不需要有任何关系。

同一个词,比如“属性”和“财产”,在不同的语言和意识形态中被重复使用,具有截然不同的含义,这真是太糟糕了。也许有人需要定义一种面向对象的语言来谈论 OOP 中的概念?UML?

于 2015-06-22T18:33:00.350 回答
0

在课堂里

public class ClassSample
{
    private int ClassAttribute;

    public int Property
    {
        get { return ClassAttribute; }
        set { ClassAttribute = value; }
    }
}

在节目中

    class Program
    {
        static void Main(string[] args)
        {
            var objectSample = new ClassSample();
            //Get Object Property
            var GetProperty = objectSample.Property;
        }
    }
于 2020-08-07T17:18:17.563 回答