这是一个新手问题,但我在Google上找不到足够的新手证明答案。
人们说“状态”是什么意思-在一般的编程中,特别是在OO编程中?
另外,什么是可变的和不可变的状态-同样,通常在编程中,尤其是在OOP中?
这是一个新手问题,但我在Google上找不到足够的新手证明答案。
人们说“状态”是什么意思-在一般的编程中,特别是在OO编程中?
另外,什么是可变的和不可变的状态-同样,通常在编程中,尤其是在OOP中?
Answers:
将值(数字,字符串,复杂的数据结构)与身份和时间点相关联时,您便具有状态。
例如,数字10本身不代表任何状态:它只是一个定义明确的数字,并且将始终是其自身:自然数10。又例如,字符串“ HELLO”是五个字符的序列,并且它完全由包含的字符及其出现的顺序描述。从现在起的五百万年里,字符串“ HELLO”仍将是字符串“ HELLO”:纯值。
为了拥有状态,您必须考虑一个世界,在这些世界中,这些纯价值与某种具有身份的实体相关联。身份是一个原始的想法:这意味着您可以区分两件事,而不管它们可能具有的其他任何属性。例如,具有相同型号,相同颜色的两辆汽车是两辆不同的汽车。
有了这些具有标识的事物,您可以将属性附加到它们,用纯值描述。例如,我的车具有蓝色的特性。您可以通过关联一对来描述这一事实
("colour", "blue")
到我的车上。该对(“颜色”,“蓝色”)是描述该特定汽车状态的纯值。
状态不仅与特定实体相关,而且还与特定时间点相关。所以,你可以说今天我的车有状态
("colour", "blue")
明天我将其重新粉刷成黑色,新状态为
("colour", "black")
请注意,实体的状态可以更改,但是其身份根据定义不会更改。好吧,当然,只要实体存在,就可以制造和销毁汽车,但是它将在其整个生命周期中保持其身份。谈论尚不存在的事物的身份没有任何意义。
如果附加到给定实体的属性的值随时间变化,则表示该实体的状态为mutable。否则,您说状态是不可变的。
最常见的实现是将实体的状态存储在某种变量(全局变量,对象成员变量)中,即存储状态的当前快照。然后使用分配来实现可变状态:每个分配操作都会用新快照替换以前的快照。此解决方案通常使用内存位置来存储当前快照。覆盖内存位置是一种破坏性操作,用新快照替换快照。(在这里,您可以找到有关此面向位置的编程方法的有趣演讲。)
另一种选择是将实体的后续状态(历史)视为值的流(可能是无限序列),例如,参见SICP的第3章。在这种情况下,每个快照都存储在不同的内存位置,并且程序可以同时检查不同的快照。当不再需要未使用的快照时,可以对其进行垃圾回收。
两种方法的优缺点
map
和的高阶函数filter
。状态只是有关内存中保存的某些事物的信息。
作为面向对象的简单练习,可以将类视为千篇一律,将cookie视为对象。您可以使用cookie切割器(类)创建cookie(实例化对象)。假设Cookie的属性之一是其颜色(可以通过使用食用色素来更改)。该Cookie的颜色以及其他属性也是其状态的一部分。
可变状态是在创建对象(cookie)之后可以更改的状态。不变状态是无法更改的状态。
不可变对象(其中没有任何国家可以改变)当你正在处理成为重要的并发,一个以上的处理器在您的计算机在同一时间,对象上操作的能力。不变性保证您可以依靠状态在对象的生存期内保持稳定和有效。
通常,对象的状态保存在“私有或成员变量”中,并通过“属性”或getter / setter方法进行访问。
我认为,在比较有状态API和无状态API时,术语“状态”(与“成员变量”之类的具体状态相反)最有用。在不提及API的情况下尝试定义“状态”有点像在不提及编程语言的情况下定义“变量”或“功能”。大多数正确答案仅对已经知道单词含义的人有意义。
例如,OpenGL可能是我所知道的最有状态的API。如果我想稍微简化一下,我们可以说它看起来像这样:
glSetCurrentVertexBufferArray(vba1);
glSetCurrentVertexBufferObject(vbo1);
glSetCurrentVertexShader(vert1);
glSetCurrentFragmentShader(frag1);
// a dozen other things
glActuallyDrawStuffWithCurrentState(GL_TRIANGLES);
几乎每个函数都只是用来传递OpenGL需要记住的某些状态,然后最后调用一个简单的函数来完成所有绘制。
(过于简化的)OpenGL的无状态版本可能看起来像这样:
glActuallyDrawStuff(vba1, vbo1, vert1, frag1, /* a dozen other things */, GL_TRIANGLES);
您会经常听到人们说状态少的API更容易推理。如果您可以控制参数的数量,我通常会同意。
据我所知,这种区别仅在您可以指定初始状态时才有意义。例如,使用C ++构造函数:
// immutable state
ImmutableWindow windowA = new ImmutableWindow(600, 400);
windowA = new ImmutableWindow(800, 600); // to change the size, I need a whole new window
// mutable state
MutableWindow windowB = new MutableWindow(600, 400);
windowB.width = 800; // to change the size, I just alter the existing object
windowB.height = 600;
很难实现一个不“记住”大小的窗口类,但是您可以决定用户在创建窗口后是否应该能够更改它的大小。
PS在OOP中,“状态” 通常表示“成员变量”,但这的确不止于此。例如,在C ++中,方法可以具有静态变量,而lambda可以通过捕获变量而成为闭包。在这两种情况下,这些变量在对函数的多次调用中均保持不变,因此可能符合状态的要求。常规函数中的局部变量也可以视状态而定,这取决于它们的使用方式(我在main()中经常使用的变量经常会计数)。
用外行话
该词典的状态:
一种。关于存在的条件或存在方式
- 状态-某种事物关于其主要属性的方式;
事物的状态是其属性在任何给定时刻具有的一组值。
在OOP中,对象的状态是任何给定时刻其属性值的快照。
Thing t = new Thing();
t.setColor("blue");
t.setPrice(100)
t.setSize("small");
它的状态是颜色为蓝色,价格为100,尺寸较小。
如果以后再做:
t.setColor("red");
您可以更改其属性之一,但也可以整体更改状态,因为对象不再与原来相同。
有时设计类是为了使它们的属性值在创建后无法更改。它们的所有属性值都传递给构造函数,或者从数据库或文件之类的源中读取,但是在那一刻之后就无法更改这些值,因为没有“ setter”方法或任何其他方式更改对象内部的值。
Thing t = new Thing("red",100,"small");
t.setColor("blue") -->> ERROR, the programmer didn't provide a setter or any other way to change the properties values after initialization.
这就是所谓的无法改变的状态。您所能做的就是销毁对象,创建一个新对象并将其赋值给相同的引用或变量。
Thing t = new Thing("red",100,"small");
t = new Thing("blue",100,"small");
// I had to create a new Thing with another color since this thing is inmutable.