Tại sao một đơn vị trả về phương thức có thể được ghi đè bằng chuỗi trả về phương thức khi các kiểu trả về không được cung cấp rõ ràng?


11

Tôi đã làm việc thông qua các ví dụ mã từ chương về Đặc điểm lập trình trong Scala Edition1 https://www.artima.com/pin1ed/traits.html

và bắt gặp một hành vi kỳ lạ vì lỗi đánh máy của tôi. Mặc dù phương thức ghi đè của một đặc điểm bên dưới đoạn mã không đưa ra bất kỳ lỗi biên dịch nào mặc dù các kiểu trả về của phương thức được ghi đè là khác Unitso với String. Nhưng khi gọi phương thức trên một đối tượng, nó trả về Đơn vị nhưng không in bất cứ thứ gì.

trait Philosophical {
    def philosophize = println("I consume memory, therefore I am!")
}

class Frog extends Philosophical {
  override def toString = "green"
  override def philosophize = "It aint easy to be " + toString + "!"
}

val frog = new Frog
//frog: Frog = green

frog.philosophize
// no message printed on console

val f = frog.philosophize
//f: Unit = ()

Nhưng khi tôi đưa ra kiểu trả về rõ ràng trong phương thức bị ghi đè, nó sẽ báo lỗi biên dịch:

class Frog extends Philosophical {
  override def toString = "green"
  override def philosophize: String = "It aint easy to be " + toString + "!"
}
         override def philosophize: String = "It aint easy to be " + toString +
                      ^
On line 3: error: incompatible type in overriding
       def philosophize: Unit (defined in trait Philosophical);
        found   : => String
        required: => Unit

Bất cứ ai có thể giúp giải thích tại sao không có lỗi biên dịch trong trường hợp đầu tiên.


Trình biên dịch đã in một gợi ý hợp lệ rằng bạn thử ghi đè một phương thức có loại kết quả khác.
Andriy Plokhotnyuk

Đúng vậy, nhưng câu hỏi của tôi là tại sao nó lại thông qua trình biên dịch trong trường hợp đầu tiên
Shanil

1
Nguyên tắc chung, luôn luôn rõ ràng về các kiểu trả về_ (đặc biệt là trên các API công khai) _. Kiểu suy luận là tuyệt vời cho các biến cục bộ, không có gì khác.
Luis Miguel Mejía Suárez

Câu trả lời:



6

Câu hỏi của tôi là tại sao nó có được thông qua trình biên dịch trong trường hợp đầu tiên

Khi bạn không chỉ định loại trả về một cách rõ ràng, nó được suy ra theo loại mà nó cần phải có overrideđể hoạt động.

Điều đó hóa ra là Unit.

Stringcác giá trị (giá trị của biểu thức tạo nên thân hàm) có thể được gán cho Unit, trình biên dịch rất vui.


1
Tuy nhiên, điều tôi muốn biết bây giờ là tại sao loại trả lại rõ ràng Stringbị từ chối. Trong Java (và tôi cũng nghĩ trong Scala), bạn được phép thu hẹp kiểu trả về khi ghi đè. Ví dụ, khi phương thức cha trả về Number, bạn có thể trả về Integer. Có lẽ void/ Unitlà đặc biệt.
Thilo

1
Điều này biên dịch, ví dụ:trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
Thilo

2
Bạn có thể thu hẹp kiểu trả về thành một kiểu con; nhưng bạn không thể thu hẹp nó thành một loại chỉ có thể được chuyển đổi hoàn toàn thành loại trả về của phương thức bị ghi đè. Stringđể Unitlà giống như một thứ hai, ngay cả khi nó không phải là chính xác đó.
Alexey Romanov

2
Ở cấp độ mã byte cũng không có kiểu trả về thu hẹp, thực tế có hai phương thức trong Frog: def philosophize : Integerdef philosophize : Number. Cách thứ hai thực sự ghi đè Philosophicalphương thức của (và gọi phương thức thứ nhất). Điều tương tự chắc chắn có thể được thực hiện cho void/ bất cứ điều gì khác, các nhà thiết kế chỉ quyết định không làm điều đó.
Alexey Romanov

2
1. Java cũng làm như vậy. 2. Có, trong mã byte, bạn có thể. Xem ví dụ stackoverflow.com/questions/18655541/ và và stackoverflow.com/questions/58065680/ .
Alexey Romanov
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.