Sự khác biệt giữa đối tượng và lớp trong Scala


636

Tôi chỉ xem qua một số hướng dẫn về Scala trên Internet và đã nhận thấy trong một số ví dụ, một đối tượng được khai báo ở đầu ví dụ.

Sự khác biệt giữa classobjecttrong Scala là gì?

Câu trả lời:


580

tl; dr

  • class C định nghĩa một lớp, giống như trong Java hoặc C ++.
  • object Otạo một đối tượng singletonO như thể hiện của một số lớp ẩn danh; nó có thể được sử dụng để giữ các thành viên tĩnh không liên quan đến các thể hiện của một số lớp.
  • object O extends Tlàm cho đối tượng Otrở thành một thể hiện của trait T; sau đó bạn có thể vượt qua Obất cứ nơi nào, một Tdự kiến.
  • nếu có a class C, thì object Cđối tượng đồng hành của lớp C; lưu ý rằng đối tượng đồng hành không tự động là một thể hiện của C.

Cũng xem tài liệu Scala cho đối tượnglớp .

object là máy chủ của các thành viên tĩnh

Thông thường, bạn cần có một objectphương thức và các giá trị / biến có sẵn mà không cần phải khởi tạo một thể hiện của một số lớp. Việc sử dụng này có liên quan chặt chẽ với staticcác thành viên trong Java.

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

Sau đó bạn có thể gọi phương thức trên bằng cách sử dụng A.twice(2).

Nếu twicelà thành viên của một số lớp A, thì bạn cần phải tạo một ví dụ trước:

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

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

Bạn có thể thấy mức độ dư thừa này như thế nào, vì twicekhông yêu cầu bất kỳ dữ liệu cụ thể nào.

object như một ví dụ đặc biệt

Bạn cũng có thể sử dụng objectchính nó như một số thể hiện đặc biệt của một lớp hoặc đặc điểm. Khi bạn làm điều này, đối tượng của bạn cần mở rộng một số traitđể trở thành một thể hiện của một lớp con của nó.

Hãy xem xét các mã sau đây:

object A extends B with C {
  ...
}

Tuyên bố này trước tiên tuyên bố một lớp ẩn danh (không thể truy cập) mở rộng cả hai BC, và khởi tạo một thể hiện duy nhất của lớp này có tên A.

Điều này có nghĩa là Acó thể được truyền cho các hàm mong đợi các đối tượng thuộc loại Bhoặc C, hoặc B with C.

Các tính năng bổ sung của object

Cũng tồn tại một số tính năng đặc biệt của các đối tượng trong Scala. Tôi khuyên bạn nên đọc tài liệu chính thức .

  • def apply(...) cho phép cú pháp không có tên phương thức thông thường của A(...)
  • def unapply(...)cho phép tạo các trình trích xuất khớp mẫu tùy chỉnh
  • nếu đi kèm với một lớp cùng tên, đối tượng sẽ đảm nhận một vai trò đặc biệt khi giải quyết các tham số ẩn

38
Nó cũng sẽ định nghĩa lớp A và tạo tất cả các phương thức trong đối tượng A là các phương thức tĩnh trên lớp A (để giao tiếp với Java). (Modulo một lỗi trong Scala 2.7 đã được sửa trong Scala 2.8)
Ken Bloom

2
@KenBloom thật sao? Tôi đã thử và không hoạt động: scala> Commerce res8: Commerce.type = Commerce $ @ 6eb2756 scala> classOf [Commerce] <console>: 23: error: không tìm thấy: gõ Commerce classOf [Commerce] ^ scala> new Commerce < bảng điều khiển>: 23: lỗi: không tìm thấy: loại Commerce new Commerce ^
Hendy I Girls

3
@Hendy: Scala sẽ không nhận ra Commercelớp, nhưng JVM và ngôn ngữ Java sẽ. (Đó là cách bạn có thể làm object Foo{ def main(args:Seq[String]) }và mong đợi chương trình chạy.)
Ken Bloom

3
Tôi nghĩ câu trả lời của ziggystar chính xác hơn, lớp là một lớp ẩn danh, trừ khi một lớp tương ứng có tên Commerce được xác định rõ ràng (thì đối tượng Commerce sẽ là đối tượng đồng hành với lớp Commerce)
Hendy I Girls

3
@DavidApltauer Tôi cá là có đủ sự tinh tế không được trả lời bởi câu trả lời của tôi. Nhưng những người có lẽ không quan trọng đối với hầu hết mọi người đọc nó. Và tôi chưa bao giờ gặp vấn đề với việc chuyển một đối tượng như một ví dụ của một số đặc điểm, điều đó không có nghĩa là chúng không tồn tại; nhưng nó nên hoạt động
ziggystar

249

A classlà một định nghĩa, một mô tả. Nó định nghĩa một loại về phương thức và thành phần của các loại khác.

An objectlà một singleton - một thể hiện của một lớp được đảm bảo là duy nhất. Đối với mỗi objecttrong mã, một lớp ẩn danh được tạo, kế thừa từ bất kỳ lớp nào bạn khai báo objectđể thực hiện. Lớp này không thể được nhìn thấy từ mã nguồn Scala - mặc dù bạn có thể nhận được nó thông qua sự phản chiếu.

Có một mối quan hệ giữa objectclass. Một đối tượng được cho là đối tượng đồng hành của một lớp nếu chúng có cùng tên. Khi điều này xảy ra, mỗi người có quyền truy cập vào các phương thức privatehiển thị khác. Những phương pháp này không được nhập tự động, mặc dù. Bạn phải nhập chúng một cách rõ ràng hoặc tiền tố chúng với tên lớp / đối tượng.

Ví dụ:

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
   }
}

1
Xin lỗi đã làm phiền bạn, nhưng có lẽ bạn có thể chỉ ra một ví dụ về cách nhập phương thức vào đối tượng đồng hành hoặc làm thế nào để thêm tiền tố vào chúng?
ithkuil

4
@ithkuil Xong. Xin lỗi về ví dụ ngớ ngẩn, tôi không thể nghĩ ra một ví dụ hay và ngắn.
Daniel C. Sobral

Điều gì xảy ra nếu tôi muốn sử dụng phương thức lớp trong Object? Điều đó có thể không? Nếu tôi có một phương thức của một lớp và tôi muốn sử dụng nó trong Object, thì nếu bạn cố gắng nhập lớp đó, bạn sẽ không thể. Cuối cùng, bạn phải tạo một hàm tạo và gọi phương thức sau đó. Vì vậy, bằng cách tạo một đối tượng đồng hành, bạn có thể truy cập các phương thức của Object bằng cách nhập nhưng không phải ngược lại. Ai đó có thể xin vui lòng xác nhận?
piyushGidel 12/05/2015

@piyushGidel Không đúng. Giả sử đối tượng có một phương thức def f(x: X) = ???, sau đó nó sẽ có thể gọi các phương thức riêng trên x, của lớp đồng hành X.
Daniel C. Sobral

Ở đây X truyền vào hàm là ví dụ của lớp XI đoán? Nếu có, thì cuối cùng bạn đang sử dụng đối tượng x để gọi phương thức của lớp X trong def f .. Phải không?
piyushGidel

76

Một đối tượng có chính xác một trường hợp (bạn không thể gọi new MyObject). Bạn có thể có nhiều phiên bản của một lớp.

Đối tượng phục vụ các mục đích tương tự (và một số bổ sung) như các phương thức và trường tĩnh trong Java.


19

Như đã được giải thích bởi nhiều người, objectđịnh nghĩa một trường hợp đơn lẻ. Một điều trong các câu trả lời ở đây mà tôi tin là còn sót lại là objectphục vụ một số mục đích.

  • Nó có thể là đối tượng đồng hành với a class/ trait, chứa những gì có thể được coi là phương thức tĩnh hoặc phương thức tiện lợi.

  • Nó có thể hoạt động giống như một mô-đun, chứa các loại và định nghĩa liên quan / công ty con, v.v.

  • Nó có thể thực hiện một giao diện bằng cách mở rộng một classhoặc một hoặc nhiều traits.

  • Nó có thể đại diện cho một trường hợp sealed traitkhông chứa dữ liệu. Về mặt này, nó thường được coi là chính xác hơn là case classkhông có tham số. Trường hợp đặc biệt của một người sealed traitchỉ có người case objectthực hiện ít nhiều là phiên bản Scala của một enum.

  • Nó có thể đóng vai trò là bằng chứng cho implicitlogic -driven.

  • Nó giới thiệu một loại singleton.

Đó là một cấu trúc rất mạnh mẽ và chung chung. Điều có thể rất khó hiểu với những người mới bắt đầu Scala là cùng một cấu trúc có thể có những cách sử dụng rất khác nhau. Và một objectcó thể phục vụ nhiều trong số những sử dụng khác nhau cùng một lúc, điều này có thể còn khó hiểu hơn.


18

Xác định một đối tượng trong Scala giống như định nghĩa một lớp trong Java chỉ có các phương thức tĩnh. Tuy nhiên, trong Scala, một đối tượng có thể mở rộng một siêu lớp khác, thực hiện các giao diện và được truyền xung quanh như thể nó là một thể hiện của một lớp. (Vì vậy, nó giống như các phương thức tĩnh trên một lớp nhưng tốt hơn).


17

Sự khác biệt chính thức -

  1. bạn không thể cung cấp các tham số hàm tạo cho Đối tượng
  2. Đối tượng không phải là một loại - bạn không thể tạo một cá thể với toán tử mới. Nhưng nó có thể có các trường, phương thức, mở rộng một siêu lớp và trộn lẫn các đặc điểm.

Sự khác biệt trong cách sử dụng:

  • Scala không có phương thức tĩnh hoặc trường. Thay vào đó bạn nên sử dụng object. Bạn có thể sử dụng nó có hoặc không có lớp liên quan. Trong trường hợp đầu tiên, nó được gọi là một đối tượng đồng hành. Bạn phải:
    1. sử dụng cùng tên cho cả lớp và đối tượng
    2. đặt chúng trong cùng một tập tin nguồn.
  • Để tạo một chương trình, bạn nên sử dụng phương thức chính object, không phải trong class.

    object Hello {
      def main(args: Array[String]) {
        println("Hello, World!")
      }
    }
  • Bạn cũng có thể sử dụng nó khi bạn sử dụng đối tượng singleton trong java.

      
        
      


"Bạn không thể cung cấp các tham số hàm tạo cho Đối tượng" Các đối tượng có phương thức áp dụng (...), có chức năng rất giống với hàm tạo. Điều này làm tôi hơi bối rối.
Danielle

7

Các đối tượng từ khóa tạo ra một kiểu singleton mới, mà là giống như một lớp học mà chỉ có một tên là trường hợp duy nhất. Nếu bạn quen thuộc với Java, việc khai báo một đối tượng trong Scala rất giống với việc tạo một thể hiện mới của một lớp ẩn danh.

Scala không có tương đương với Java tĩnh từ khóa, và một đối tượng thường được sử dụng trong Scala, nơi bạn có thể sử dụng một lớp với các thành viên tĩnh trong Java.


6

Đối tượng là một lớp nhưng nó đã có (là) một thể hiện, vì vậy bạn không thể gọi new ObjectName. Mặt khác, Class chỉ là kiểu và nó có thể là một thể hiện bằng cách gọi new ClassName().


4

Trong scala, không có statickhái niệm. Vì vậy, scala tạo một đối tượng singleton để cung cấp điểm vào cho việc thực hiện chương trình của bạn. Nếu bạn không tạo đối tượng singleton, mã của bạn sẽ biên dịch thành công nhưng sẽ không tạo ra bất kỳ đầu ra nào. Các phương thức được khai báo bên trong Singleton Object có thể truy cập được trên toàn cầu. Một đối tượng singleton có thể mở rộng các lớp và đặc điểm.

Ví dụ đối tượng Scala Singleton

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


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

Đầu ra:

Hello, This is Singleton Object

Trong scala, khi bạn có một lớp có cùng tên với đối tượng singleton, nó được gọi là lớp đồng hành và đối tượng singleton được gọi là đối tượng đồng hành.

Cả lớp đồng hành và đối tượng đồng hành của nó đều phải được định nghĩa trong cùng một tệp nguồn.

Ví dụ về đối tượng đồng hành 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.")  
    }  
}  

Đầu ra:

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

Trong scala, một lớp có thể chứa:

1. Thành viên dữ liệu

2. Phương thức thành viên

3. Khối xây dựng

4. Lớp lồng nhau

5. Thông tin siêu hạng, v.v.

Bạn phải khởi tạo tất cả các biến thể hiện trong lớp. Không có phạm vi mặc định. Nếu bạn không chỉ định phạm vi truy cập, nó là công khai. Phải có một đối tượng trong đó phương thức chính được xác định. Nó cung cấp điểm khởi đầu cho chương trình của bạn. Ở đây, chúng tôi đã tạo ra một ví dụ về lớp.

Ví dụ mẫu của 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);  
    }  
} 

Tôi xin lỗi, tôi đã quá muộn nhưng tôi hy vọng nó sẽ giúp bạn.


2

Lớp Scala giống như Lớp Java nhưng scala không cung cấp cho bạn bất kỳ phương thức nhập nào trong lớp, giống như phương thức chính trong java. Phương thức chính liên quan đến từ khóa đối tượng. Bạn có thể nghĩ từ khóa đối tượng là tạo một đối tượng đơn lẻ của một lớp được định nghĩa ngầm.

thêm thông tin kiểm tra lớp bài viết này và từ khóa đối tượng trong lập trình scala


2

Đối tượng tương tự như lớp tĩnh trong Java với một số phần mở rộng, đặc tính tĩnh có nghĩa là lớp tĩnh không cần tạo đối tượng khi đặt vào JVM, nó có thể được sử dụng trực tiếp bởi tên lớp và cùng thể hiện (cùng trạng thái dữ liệu ) được chia sẻ bất cứ nơi nào nó được sử dụng.


1

Một lớp cũng giống như bất kỳ lớp nào khác trong các ngôn ngữ khác. Bạn định nghĩa lớp giống như bất kỳ ngôn ngữ nào khác với một số khác biệt cú pháp.

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

Tuy nhiên, đối tượng là một lớp chỉ có một đối tượng. Điều này làm cho nó thú vị vì nó có thể được sử dụng để tạo các thành viên tĩnh của một lớp bằng cách sử dụng đối tượng đồng hành . Đối tượng đồng hành này có quyền truy cập vào các thành viên riêng của định nghĩa lớp và nó có cùng tên với lớp bạn đang xác định.

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()

Ngoài ra, điểm đáng chú ý là lớp đối tượng được tạo ra một cách lười biếng, đó là một điểm quan trọng khác. Vì vậy, những điều này không được khởi tạo trừ khi chúng là cần thiết trong mã của chúng tôi.

Nếu bạn đang xác định việc tạo kết nối cho JDBC, bạn có thể tạo chúng bên trong đối tượng để tránh trùng lặp giống như chúng ta làm trong Java với các đối tượng đơn lẻ.


0

Nếu bạn đến từ nền java, khái niệm lớp trong scala tương tự như Java, nhưng lớp trong scala không chứa các thành viên tĩnh.

Các đối tượng trong scala là loại singleton mà bạn gọi các phương thức bên trong nó bằng tên đối tượng, trong đối tượng scala là một từ khóa và trong đối tượng java là một thể hiện của lớp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.