繁体   English   中英

Scala类是否具有像Python一样的“自我”?

[英]Do scala classes have “self” like Python?

例如,如果我有

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

这些变量仅在myClass的特定实例中“存在”,还是在所有对象之间共享“类范围”变量? 如果是后者,如何使这些变量仅对象化?

是的,这是实现this ,像在Java或C ++。 您不必像在python中那样在方法调用中显式传递它。

然后,在示例中创建的是实例变量,也称为成员。 它们属于该类的实例,即它们不在所有相同类的所有对象上共享( 类变量 )。 对于后者,您可能需要使用伴随方案

最后,您可能想更多地了解scala,例如此处的本教程 ,或者由@IanAuld提供给python开发人员的书,或者在scala的创建提供的Coursera上运行scala课程

和顺便说一句,欢迎堆栈溢出!


编辑:

因此,在Scala中我在此处设置的方式是实例变量,而如果我在Python中执行了相同的通用方法(就放置而言),它们将是类变量? 还是您说我必须在某处添加“ this”以使它们成为实例变量?

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

蟒蛇

Python的设计思想是类(和模块,btw)是dict ,在早期版本的python中,您甚至可以通过myclass.__dict__成员访问该类的成员,即使今天该dict是“隐藏的”通过实现,仍然可以通过getattrsetattr访问。

这个想法是python如何使用类的中心,因为一切都是通过猴子补丁完成的,即在运行时更改和实际定义类定义。

class Foo:
    pass
foo = Foo()
foo.bar = 1
print(foo.bar)

python基本的另一件事是一切都是显式的。 这就是为什么当你声明一个方法,你传递当前类作为参数传递给方法的明确的参考:

class Foo:
    def foobar(self):
        self.bar = 1
print(foo.bar)

但这实际上等效于:

class Foo:
    pass
def foobar(self):
    self.bar = 1
foo = Foo()
foobar(foo)
print(foo.bar)

以下行为很好地说明了猴子修补的含义:

class Foo:
    def foobar(self):
        print(self.bar)
foo = Foo()
foo.bar = 1
foo.foobar() # prints 1

因此,当您实际在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]

总而言之,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
}

因此,在这里您定义了实例变量,并为它们提供了一个“默认”值,这是您在__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
  }

Square是一个接受参数的函数,并返回一个实例,该实例具有在该函数范围内定义的方法。 因此,外部“函数”实际上是构造函数,内部函数是方法。

现在,scala中不存在任何实际的类变量,为此,您可能更喜欢使用配套设计模式(请参见有关SO的答案链接)。

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

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

您的someName变量是不可变的。 这意味着您不能在实例中对其进行修改,因此,所有实例都相同。 所以以某种方式,它看起来像类变量,即使不是,它们实际上是实例变量。

就像我在python中的dict示例一样,这也不是完全准确的,因为关于这些机制还有更多的知识要知道-我什至没有在这方面做铺垫,但是它的目的是证明Scala(一种功能强大的功能)之间的巨大差异/ object语言和python-一种🐒-patching/目标语言。

现在从过程范式语言迈向功能性语言迈出了一大步,感觉就像是在学习重新开发,但这绝对是值得的,因为它会教给您一种不同的程序思维方式,不仅您学习了新语言和新范式,但是通过更好的实践和更多地关心打字,它也将使您以已经知道的语言更好地发展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM