scala类是否像Python一样"自我"?

use*_*410 2 python scala class

例如,如果我有

object Solution {
    class myClass(A: Array[Int]){
        val something: Int = A.length;
        val another: Int = something/2;
        val someName = "blah"
 ...
 ...
Run Code Online (Sandbox Code Playgroud)

这些变量是否仅存在于myClass的特定实例中,或者它们是否在所有对象之间共享"类范围"变量?如果是后者,我该如何使这些变量成为对象?

zmo*_*zmo 5

是的,它实现为this,如Java或C++.您不必在方法调用中显式传递它,就像在python中一样.

那么你在你的例子中创建的是实例变量,也称为成员.它们属于类的实例,即它们不在所有相同类(类变量)的所有对象上共享.对于后者,您可能希望使用配套方案.

最后,您可能想要更多地阅读有关scala的内容,例如本教程,或者@IanAuld提供的python devs或者scala的创建者提供的课程上scala课程.

顺便说一句,欢迎Stack Overflow!


编辑:

所以我在Scala中设置它的方式是实例变量,而如果我在Python中使用了相同的通用方法(在放置方面),它们是类变量吗?或者你是说我必须在某处添加"this"以使它们成为实例变量?

我看到你在哪里感到困惑.Python和Scala在面向对象编程方法上有很大不同.首先让我们谈谈python:

蟒蛇

Python的设计理念是类(和模块,btw)dict,在早期版本的python中你甚至可以通过成员访问类的myclass.__dict__成员,而今天,即使该dict被实现"隐藏",它仍然可以通过getattr和访问setattr.

这个想法是python如何与类一起工作的核心,因为一切都是通过猴子修补完成的,即在运行时更改和实际定义类定义.

class Foo:
    pass
foo = Foo()
foo.bar = 1
print(foo.bar)
Run Code Online (Sandbox Code Playgroud)

python中另一个基本的东西是一切都是明确的.这就是为什么在声明方法时,将当前类的引用显式传递给方法:

class Foo:
    def foobar(self):
        self.bar = 1
print(foo.bar)
Run Code Online (Sandbox Code Playgroud)

但这实际上相当于:

class Foo:
    pass
def foobar(self):
    self.bar = 1
foo = Foo()
foobar(foo)
print(foo.bar)
Run Code Online (Sandbox Code Playgroud)

并且以下行为很好地说明了猴子修补的内容:

class Foo:
    def foobar(self):
        print(self.bar)
foo = Foo()
foo.bar = 1
foo.foobar() # prints 1
Run Code Online (Sandbox Code Playgroud)

所以当你在python中实际定义成员时,你真正在做的是用新成员修补当前实例.

现在,当你进行类实例时,如果我们使用我告诉你的dict表示,你所做的实际上就像下面那样:

Foo = dict(a=1, b=[2]) # class definition with class variables
foo = Foo.copy()       # create instance
foo['b'].append(3)     # use a class variable's instance
print(Foo['b']) # prints: [2,3]
Run Code Online (Sandbox Code Playgroud)

总而言之,python对OOP有一种非常特殊的方法,它完全基于类的行为有点像dict的想法,并且它们应该被猴子修补定义(这就是为什么当你创建一个类时,约定是在构造函数中声明所有成员).这就是为什么python不被认为是一种"纯粹的"面向对象语言(这只是语言的属性,而不是资格)的原因.

斯卡拉

Scala被定义为纯粹的功能性和纯面向对象语言.而语言的这两个属性使它与python非常不同.我不打算深入解释功能性编程的深度,但我强烈建议你按照课程阅读有关它的书籍和Scala,以便掌握它.

因此,在定义类时,在Scala中,您可以执行以下操作(示例由我链接的教程提供):

class Square {
    var x: Double = 0
    var y: Double = 0
    var width: Double = 0
    var height: Double = 0
    def area(): Double = width * height
}
Run Code Online (Sandbox Code Playgroud)

所以在这里你定义了实例变量,你给它们一个"默认"值,这是你在__init__()构造函数中在python中定义的.然后定义一个方法.

但是因为scala是有用的,你可以在类定义中有另一个读数:

class Square(
    private var x: Double,
    private var y: Double,
    private var width: Double,
    private var height: Double
  ) {
    def area(): Double = width * height
  }
Run Code Online (Sandbox Code Playgroud)

Square是一个接受参数的函数,它返回一个具有方法的实例,在该函数的范围内定义.那么,外部"函数"实际上是一个构造函数,内部函数是方法.

现在,scala中不存在实际的类变量,为此,您可能更喜欢使用伴随设计模式(参见关于它的SO答案链接).

但顺便说一句,因为您在示例中使用的someName变量的属性:

class myClass(A: Array[Int]){
    val something: Int = A.length;
    val another: Int = something/2;
    val someName = "blah"
Run Code Online (Sandbox Code Playgroud)

你的someName变量是不可变的.这意味着您无法在实例中修改它,因此对于您的所有实例都是相同的.所以不知何故,它看起来像类变量,即使它不是,它们实际上是实例变量.

就像我在python中的dict示例一样,这并不完全准确,因为有更多关于这些机制的知识 - 我甚至没有在这里表面,但它的作用是为了展示Scala之间的巨大差异 - 一个功能/ object语言和python - a -patching/object语言.

现在从程序范式语言转变为功能性语言相当重要的一步,感觉就像再次学习开发一样,但它绝对值得,因为它会教你一种不同的方式来思考你的程序,而不仅仅是你学习一个新语言和新范例,但它也将通过更好的实践和更多关于打字的关注,使您在已知语言中更好地发展.