ทำไมเมธอดที่ส่งคืนยูนิตสามารถถูกแทนที่ด้วยเมธอดที่ส่งคืนสตริงเมื่อชนิดการส่งคืนไม่ได้รับอย่างชัดเจน?


11

ฉันกำลังทำงานผ่านตัวอย่างโค้ดจากบทเกี่ยวกับลักษณะในการเขียนโปรแกรมใน Scala Edition1 https://www.artima.com/pins1ed/traits.html

และเจอพฤติกรรมแปลก ๆ เพราะพิมพ์ผิดของฉัน ในขณะที่วิธีการลักษณะดังต่อไปนี้รหัสข้อมูลเท่านั้นเอาชนะไม่ได้ให้รวบรวมข้อผิดพลาดใด ๆ แม้ว่าประเภทการกลับมาของวิธีการที่แตกต่างกันแทนที่เป็นVSUnit Stringแต่เมื่อเรียกวิธีการบนวัตถุมันจะส่งคืนหน่วย แต่ไม่ได้พิมพ์อะไร

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

แต่เมื่อฉันให้กลับประเภทชัดเจนในวิธีการแทนที่มันให้ข้อผิดพลาดในการรวบรวม:

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

ทุกคนสามารถช่วยอธิบายว่าทำไมไม่มีข้อผิดพลาดในการรวบรวมในกรณีแรก


คอมไพเลอร์ได้พิมพ์คำใบ้ที่ถูกต้องซึ่งคุณลองแทนที่วิธีที่มีประเภทผลลัพธ์ต่างกัน
Andriy Plokhotnyuk

ใช่แน่นอน แต่คำถามของฉันคือทำไมมันถึงผ่านคอมไพเลอร์ในกรณีที่ 1
Shanil

1
กฎของหัวแม่มือต้องชัดเจนเกี่ยวกับประเภทของการส่งคืน _ (โดยเฉพาะกับ API สาธารณะ) _ การอนุมานประเภทนั้นยอดเยี่ยมสำหรับตัวแปรท้องถิ่นไม่มีอะไรอื่น
Luis Miguel

คำตอบ:


8

เมื่อชนิดที่คาดว่าจะเป็นUnit, ค่าใด ๆ สามารถเป็นที่ยอมรับ :

ทิ้งค่า

ถ้าeมีประเภทค่าบางและชนิดที่คาดว่าจะเป็นUnit, จะถูกแปลงเป็นชนิดที่คาดว่าจะโดยการฝังไว้ในคำว่าe{ e; () }


6

คำถามของฉันคือทำไมมันถึงคอมไพเลอร์ในกรณีที่ 1

เมื่อคุณไม่ได้ระบุประเภทที่ส่งคืนอย่างชัดเจนมันถูกอนุมานด้วยประเภทที่ต้องมีเพื่อoverrideให้การทำงาน

Unitที่เปิดออกมาเป็น

เนื่องจากสามารถStringกำหนดค่า (ค่าของนิพจน์ที่ทำหน้าที่ของร่างกาย) Unitคอมไพเลอร์จึงมีความสุข


1
อย่างไรก็ตามสิ่งที่ฉันต้องการทราบในตอนนี้คือสาเหตุที่ประเภทการส่งคืนที่ชัดเจนStringถูกปฏิเสธ ใน Java (และฉันคิดว่าใน Scala ด้วย) คุณได้รับอนุญาตให้จำกัดประเภทการส่งคืนเมื่อเอาชนะ ตัวอย่างเช่นเมื่อวิธีการปกครองผลตอบแทนที่คุณสามารถกลับNumber Integerอาจจะvoid/ Unitเป็นพิเศษ
Thilo

1
คอมไพล์นี้เช่น:trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
Thilo

2
คุณสามารถ จำกัด ประเภทการคืนให้แคบลงได้ แต่คุณไม่สามารถ จำกัด ให้เป็นประเภทที่สามารถแปลงเป็นประเภทส่งคืนของเมธอดแทนที่โดยปริยาย StringจะUnitเป็นเหมือนคนที่สองแม้ว่าจะไม่ได้เป็นว่าที่
Alexey Romanov

2
ในระดับ bytecode ไม่มีการกวดขันทั้งชนิดกลับมีจริงสองวิธีในFrog: และdef philosophize : Integer def philosophize : Numberอันที่สองจะแทนที่Philosophicalเมธอดของ (และเรียกอันแรก) สิ่งเดียวกันสามารถทำได้void/ สิ่งอื่นนักออกแบบเพียงตัดสินใจที่จะไม่ทำมัน
Alexey Romanov

2
1. Java ทำเช่นเดียวกัน 2. ใช่ใน bytecode คุณสามารถ ดูเช่นstackoverflow.com/questions/18655541/...และstackoverflow.com/questions/58065680/...
Alexey Romanov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.