简体   繁体   English

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

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

For example if I have 例如,如果我有

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

Do these variables "exist" only for a particular instance of myClass or are they "class-wide" variables shared among all objects? 这些变量仅在myClass的特定实例中“存在”,还是在所有对象之间共享“类范围”变量? If it's the latter, how do I make these variables object-only? 如果是后者,如何使这些变量仅对象化?

Yes, and it is implemented as this , like in Java or C++. 是的,这是实现this ,像在Java或C ++。 You don't have to pass it explicitly at the method call, like in python. 您不必像在python中那样在方法调用中显式传递它。

Then what you're creating in your example are instance variables, also called members. 然后,在示例中创建的是实例变量,也称为成员。 They belong to instances of the class, ie they are not shared on all objects of all the same class ( class variables ). 它们属于该类的实例,即它们不在所有相同类的所有对象上共享( 类变量 )。 For the latter, you might want to use the companion scheme . 对于后者,您可能需要使用伴随方案

Finally, you might want to give some more reading about scala, like this tutorial here , or the one for python devs courtesy of @IanAuld or run the scala course on coursera which is offered by the creators of scala. 最后,您可能想更多地了解scala,例如此处的本教程 ,或者由@IanAuld提供给python开发人员的书,或者在scala的创建提供的Coursera上运行scala课程

And BTW, welcome on Stack Overflow! 和顺便说一句,欢迎堆栈溢出!


edit: 编辑:

So the way I have it set up here in Scala are instance variables, whereas if I had done this same general approach (in terms of placement) in Python, they'd be class variables? 因此,在Scala中我在此处设置的方式是实例变量,而如果我在Python中执行了相同的通用方法(就放置而言),它们将是类变量? Or are you saying I have to add "this" somewhere to make them instance variables? 还是您说我必须在某处添加“ this”以使它们成为实例变量?

I see where you're getting confused. 我知道您在哪里感到困惑。 Python and Scala are very different in their approaches to object oriented programing. Python和Scala在面向对象编程的方法上有很大不同。 First let's talk about python a bit: 首先让我们谈谈python:

python 蟒蛇

Python has been designed with the idea that classes (and modules, btw) are dict , in earlier versions of python you could even access the members of the class through the myclass.__dict__ member, and today, even though that dict is "hidden" by the implementation, it's still accessible through getattr and setattr . Python的设计思想是类(和模块,btw)是dict ,在早期版本的python中,您甚至可以通过myclass.__dict__成员访问该类的成员,即使今天该dict是“隐藏的”通过实现,仍然可以通过getattrsetattr访问。

This idea is central to how python works with classes, as everything is done through monkey patching , ie changing, and actually defining, the class definition at runtime. 这个想法是python如何使用类的中心,因为一切都是通过猴子补丁完成的,即在运行时更改和实际定义类定义。

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

Another thing that is fundamental in python is that everything is explicit. python基本的另一件事是一切都是显式的。 This is why when you declare a method, you pass explicitly the reference of the current class as a parameter to the method: 这就是为什么当你声明一个方法,你传递当前类作为参数传递给方法的明确的参考:

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

but that is actually equivalent to doing: 但这实际上等效于:

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

and the following behaviour illustrate quite well what monkey patching is about: 以下行为很好地说明了猴子修补的含义:

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

so when you're actually defining members in python, what you're really doing is monkey patching the current instance with new members. 因此,当您实际在python中定义成员时,您真正要做的就是用新成员来修补当前实例。

Now, when you do class instances , what you do is actually behaving like the following, if we use the dict representation I told you about: 现在,当您执行类实例时,如果我们使用我告诉您的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]

All in all, python has a very special approach to OOP, that is entirely based on the ideas that class behave a bit like dict and that they shall be monkey patched to be defined (which is why when you create a class, the convention is to declare all your members in your constructor). 总而言之,python对OOP有一种非常特殊的方法,它完全基于类的行为有点像dict的思想,并且它们应该被猴子修补以定义(这就是为什么在创建类时,约定是在构造函数中声明所有成员)。 And those are reasons why python is not considered a "pure" object oriented language (which is just a property of the language, not a qualification). 这就是为什么python不被视为“纯”面向对象语言(这只是该语言的一种属性,而不是一种限定条件)的原因。

Scala 斯卡拉

Scala is being defined as a pure functional and pure object oriented language. Scala被定义为一种纯功能性和纯面向对象的语言。 And those two properties of the language makes it very, very different from python. 而且该语言的这两个属性使其与python非常非常不同。 I'm not gonna get into length into explaining functional programing in depth, but I highly recommend you to follow a course and read books about it and Scala to have a good grip at it. 我不会深入解释函数式编程,但是我强烈建议您学习一门课程并阅读有关它的书籍,并充分掌握Scala的知识。

So in Scala when you define a class, you can do the following (example courtesy of the tutorial I linked): 因此,在Scala中定义类时,可以执行以下操作(示例由我链接的教程提供):

class Square {
    var x: Double = 0
    var y: Double = 0
    var width: Double = 0
    var height: Double = 0
    def area(): Double = width * height
}

so here you defined instance variables and you give them a "default" value, which is what you'd define in python within the __init__() constructor. 因此,在这里您定义了实例变量,并为它们提供了一个“默认”值,这是您在__init__()构造函数中的python中定义的值。 And then you define a method. 然后定义一个方法。

But because scala is functional, you can have another reading at the class definition: 但是由于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 is a function which takes parameters, and returns an instance that has methods, being defined within the scope of that function. Square是一个接受参数的函数,并返回一个实例,该实例具有在该函数范围内定义的方法。 So then, the outer "function" is actually a constructor, and the inner functions are the methods. 因此,外部“函数”实际上是构造函数,内部函数是方法。

Now, there's no actual class variables existing in scala, and to do so, you might prefer to use the companion design pattern (cf the SO answer link about it). 现在,scala中不存在任何实际的类变量,为此,您可能更喜欢使用配套设计模式(请参见有关SO的答案链接)。

But incidentally, because the property of the someName variable you're using in your example: 但顺便说一句,因为您在示例中使用的someName变量的属性:

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

your someName variable is non mutable. 您的someName变量是不可变的。 What that means is that you cannot modify it within the instances, and thus it is the same for all your instances. 这意味着您不能在实例中对其进行修改,因此,所有实例都相同。 So somehow, it looks like class variable, even though it's not, they really are instance variables. 所以以某种方式,它看起来像类变量,即使不是,它们实际上是实例变量。

Like my dict example in python, this is not entirely exact as there's much more to know about those mechanisms — I'm not even scratching the surface here, but it works for the purpose of demonstrating the huge difference there is between Scala — a functional/object language, and python — a 🐒-patching/object language. 就像我在python中的dict示例一样,这也不是完全准确的,因为关于这些机制还有更多的知识要知道-我什至没有在这方面做铺垫,但是它的目的是证明Scala(一种功能强大的功能)之间的巨大差异/ object语言和python-一种🐒-patching/目标语言。

Now going from a procedural paradigm language to a functional one quite a big step, it feels like learning again to develop, but it's definitely worth it, as it's going to teach you a different way of thinking your programs, and not only you learn a new language and a new paradigm, but it's also going to make you develop better in the languages you already know by having better practices and caring more about typing. 现在从过程范式语言迈向功能性语言迈出了一大步,感觉就像是在学习重新开发,但这绝对是值得的,因为它会教给您一种不同的程序思维方式,不仅您学习了新语言和新范式,但是通过更好的实践和更多地关心打字,它也将使您以已经知道的语言更好地发展。

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

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