ChatGPT解决这个技术问题 Extra ChatGPT

Scala中对象和类之间的区别

我只是在 Internet 上浏览一些 Scala 教程,并注意到在一些示例中,在示例开头声明了一个对象。

Scala 中的 classobject 有什么区别?


z
ziggystar

tl;博士

类定义了一个类,就像在 Java 或 C++ 中一样。

对象 O 创建一个单例对象 O 作为某个匿名类的实例;它可用于保存与某个类的实例无关的静态成员。

对象 O 扩展 T 使对象 O 成为特征 T 的实例;然后,您可以将 O 传递到任何地方,预期为 T。

如果存在类 C,则对象 C 是类 C 的伴生对象;请注意,伴随对象不会自动成为 C 的实例。

另请参阅 objectclass 的 Scala 文档。

对象作为静态成员的宿主

大多数情况下,您需要一个 object 来保存无需先实例化某个类的实例即可使用的方法和值/变量。这种用法与 Java 中的 static 成员密切相关。

object A {
  def twice(i: Int): Int = 2*i
}

然后您可以使用 A.twice(2) 调用上述方法。

如果 twice 是某个类 A 的成员,那么您需要先创建一个实例:

class A() {
  def twice(i: Int): Int = 2 * i
}

val a = new A()
a.twice(2)

您可以看到这是多么多余,因为 twice 不需要任何特定于实例的数据。

对象作为一个特殊的命名实例

您还可以将 object 本身用作类或特征的一些特殊实例。当您这样做时,您的对象需要扩展一些 trait 才能成为它的子类的实例。

考虑以下代码:

object A extends B with C {
  ...
}

该声明首先声明了一个扩展 BC 的匿名(不可访问)类,并实例化了名为 A 的此类的单个实例。

这意味着可以将 A 传递给需要 BCB with C 类型的对象的函数。

对象的附加功能

Scala 中还存在一些对象的特殊功能。我建议阅读official documentation

def apply(...) 启用 A(...) 的常用方法无名称语法

def unapply(...) 允许创建自定义模式匹配提取器

如果伴随同名的类,则对象在解析隐式参数时承担特殊角色


它还将定义类 A,并将对象 A 中的所有方法创建为类 A 上的静态方法(用于与 Java 交互)。 (对 Scala 2.7 中的一个错误进行取模,该错误已在 Scala 2.8 中修复)
@KenBloom 真的吗?我试过但没有用: scala> Commerce res8: Commerce.type = Commerce$@6eb2756 scala> classOf[Commerce] :23: error: not found: type Commerce classOf[Commerce] ^ scala> new Commerce <控制台>:23:错误:未找到:键入Commerce new Commerce ^
@Hendy:Scala 不会识别 Commerce 类,但 JVM 和 Java 语言会。 (这就是您可以执行 object Foo{ def main(args:Seq[String]) } 并期望程序运行的方式。)
我认为 ziggystar 的回答更准确,该类是匿名类,除非显式定义了名为 Commerce 的相应类(那么 Commerce 对象将是 Commerce 类的伴随对象)
@DavidApltauer 我敢打赌,我的回答没有涵盖足够多的微妙之处。但对于大多数阅读本文的人来说,这些可能并不重要。而且我从来没有遇到过将对象作为某些特征的实例传递的问题,这并不意味着它们不存在;但它应该工作。
D
Daniel C. Sobral

class 是一个定义,一个描述。它根据其他类型的方法和组合来定义一个类型。

object 是一个单例——一个保证唯一的类的实例。对于代码中的每个 object,都会创建一个匿名类,该类继承自您声明 object 以实现的任何类。这个类不能从 Scala 源代码中看到——尽管你可以通过反射得到它。

objectclass 之间存在关系。如果一个对象具有相同的名称,则称它们是一个类的伴生对象。发生这种情况时,每个人都可以访问对方的 private 可见性方法。但是,这些方法不会自动导入。您要么必须显式导入它们,要么在它们前面加上类/对象名称。

例如:

class X {
  // class X can see private members of object X
  // Prefix to call
  def m(x: Int) = X.f(x)

  // Import and use
  import X._
  def n(x: Int) = f(x)

  private def o = 2
}

object X {
  private def f(x: Int) = x * x

  // object X can see private members of class X
  def g(x: X) = {
    import x._
    x.o * o // fully specified and imported
   }
}

很抱歉打扰您,但您能否指出一个有关如何将方法导入伴随对象或如何为它们添加前缀的示例?
@ithkuil 完成。很抱歉这个愚蠢的例子,我想不出一个又好又短的例子。
如果我想在 Object 中使用类方法怎么办?那可能吗?如果我有一个类的方法并且我想在 Object 中使用它,那么如果你尝试导入该类,你将无法做到。最终,您必须创建一个构造函数并调用该方法。因此,通过创建伴随对象,您可以使用 import 访问 Object 的方法,反之则不行。有人可以验证吗?
@piyushGoyal 不正确。假设该对象有一个方法 def f(x: X) = ???,那么它将能够调用伴随类 Xx 上的私有方法。
这里传入的函数中的 X 是类 XI 的实例猜猜?如果是,那么最终您将使用对象 x 在 def f. 中调用 X 类的方法。对吗?
j
jos

一个对象只有 一个 实例(您不能调用 new MyObject)。您可以拥有一个类的多个实例。

Object 与 Java 中的静态方法和字段具有相同的(以及一些额外的)目的。


a
acjay

正如许多人所解释的,object 定义了一个单例实例。我认为这里的答案中被忽略的一件事是 object 有多种用途。

它可以是类/特征的伴随对象,包含可能被视为静态方法或便利方法的内容。

它可以像一个模块一样工作,包含相关/附属类型和定义等。

它可以通过扩展一个类或一个或多个特征来实现接口。

它可以表示不包含数据的密封特征的情况。在这方面,它通常被认为比没有参数的案例类更正确。仅具有案例对象实现者的密封特征的特殊情况或多或少是枚举的 Scala 版本。

它可以作为隐式驱动逻辑的证据。

它引入了单例类型。

这是一个非常强大和通用的结构。让 Scala 初学者感到非常困惑的是,相同的构造可以有截然不同的用途。并且 object 可以同时提供许多这些不同的用途,这可能会更加令人困惑。


e
eugenevd

在 Scala 中定义一个对象就像在 Java 中定义一个只有静态方法的类。然而,在 Scala 中,一个对象可以扩展另一个超类,实现接口,并像一个类的实例一样被传递。 (所以它就像一个类上的静态方法,但更好)。


M
Manindar

形式上的区别——

您不能为 Objects 提供构造函数参数 Object 不是类型 - 您不能使用 new 运算符创建实例。但它可以有字段、方法、扩展超类和混合特征。

用法上的区别:

Scala 没有静态方法或字段。相反,您应该使用对象。您可以在有或没有相关类的情况下使用它。在第一种情况下,它被称为伴随对象。您必须: 为类和对象使用相同的名称 将它们放在同一个源文件中。

对类和对象使用相同的名称

将它们放在同一个源文件中。

要创建程序,您应该在对象中使用 main 方法,而不是在类中。对象 Hello { def main(args: Array[String]) { println("Hello, World!") } }

你也可以像在 java 中使用单例对象一样使用它。


“你不能为对象提供构造函数参数” 对象有 apply(...) 方法,它的功能很像构造函数。这让我有点困惑。
B
Bhaskar Das

在 Scala 中,没有 static 概念。因此 scala 创建了一个单例对象来为您的程序执行提供入口点。如果您不创建单例对象,您的代码将成功编译但不会产生任何输出。在 Singleton Object 中声明的方法可以全局访问。单例对象可以扩展类和特征。

Scala 单例对象示例

object Singleton{  
    def main(args:Array[String]){  
        SingletonObject.hello()         // No need to create object.  
    }  
}  


object SingletonObject{  
    def hello(){  
        println("Hello, This is Singleton Object")  
    }  
}  

输出:

Hello, This is Singleton Object

在scala中,当你有一个与单例对象同名的类时,它被称为伴生类,单例对象被称为伴生对象。

伴随类及其伴随对象都必须在同一个源文件中定义。

Scala 伴随对象示例

class ComapanionClass{  
    def hello(){  
        println("Hello, this is Companion Class.")  
    }  
}  
object CompanoinObject{  
    def main(args:Array[String]){  
        new ComapanionClass().hello()  
        println("And this is Companion Object.")  
    }  
}  

输出:

Hello, this is Companion Class.
And this is Companion Object.

在 Scala 中,一个类可以包含:

1.数据成员

2.会员方式

3.构造函数块

4.嵌套类

5.超类信息等

您必须初始化类中的所有实例变量。没有默认范围。如果您不指定访问范围,则它是公共的。必须有一个定义了 main 方法的对象。它为您的程序提供了起点。在这里,我们创建了一个类的示例。

Scala 类示例

class Student{  
    var id:Int = 0;                         // All fields must be initialized  
    var name:String = null;  
}  
object MainObject{  
    def main(args:Array[String]){  
        var s = new Student()               // Creating an object  
        println(s.id+" "+s.name);  
    }  
} 

对不起,我来晚了,但我希望它能帮助你。


佚名

object 关键字创建了一个新的单例类型,它就像一个只有一个命名实例的类。如果您熟悉 Java,那么在 Scala 中声明一个对象很像创建一个匿名类的新实例。

Scala 没有等效于 Java 的 static 关键字,并且对象经常在 Scala 中使用,您可以在 Java 中使用具有静态成员的类。


Y
Yonggoo Noh

Object 是一个类,但它已经有一个实例,因此您不能调用 new ObjectName。另一方面,Class 只是类型,它可以通过调用 new ClassName() 成为实例。


P
Piyush Patel

一个类就像其他语言中的任何其他类一样。您定义类就像任何其他具有一些语法差异的语言一样。

class Person(val name: String)
val me = new Person("My name")

但是,对象是一个只有单个对象的类。这很有趣,因为它可以用于使用伴随对象创建类的静态成员。这个伴生对象可以访问类定义的私有成员,并且它与您定义的类同名。

class Person(var name: String) {

  import Person._

  def hi(): String = sayHello(name)
}

object Person {
  private def sayHello(name: String): String = "Hello " + name
}

val me = new Person("My name")
me.hi()

此外,值得注意的一点是对象类是延迟创建的,这是另一个重要的一点。因此,除非我们的代码需要它们,否则它们不会被实例化。

如果您正在为 JDBC 定义连接创建,您可以在对象内部创建它们以避免重复,就像我们在 Java 中使用单例对象所做的那样。


F
FOD

Scala 类与 Java 类相同,但 scala 没有为您提供类中的任何入口方法,如 java 中的 main 方法。与对象关键字关联的主要方法。您可以将 object 关键字视为创建隐式定义的类的单例对象。

更多信息查看这篇文章class and object keyword in scala programming


S
Sangeeta

对象在某种程度上类似于Java中的静态类,静态特性意味着静态类在放到JVM中时不需要创建对象,可以直接使用类名和相同的实例(相同的数据状态) ) 在任何使用的地方共享。


V
Vivek

如果您来自 java 背景,scala 中的类的概念有点类似于 Java,但 scala 中的类不能包含静态成员。

scala中的对象是单例类型,您可以使用对象名称在其中调用方法,在scala中对象是关键字,在java中对象是类的实例