อะไรคือเหตุผลเบื้องหลังการมีวัตถุร่วมใน Scala


107

มีกรณีที่จำเป็นต้องใช้วัตถุร่วม (ซิงเกิลตัน) สำหรับคลาสหรือไม่? เหตุใดฉันจึงต้องการสร้างคลาสพูดFooและสร้างอ็อบเจ็กต์ที่แสดงร่วมด้วย



ดูstackoverflow.com/a/9806136/736957ซึ่งรวบรวมคำตอบที่ดีได้ที่นี่
หัวเราะ

คำตอบ:


82

โดยพื้นฐานแล้ววัตถุที่แสดงร่วมจะเป็นสถานที่ที่สามารถวางเมธอดแบบ "คงที่" ได้ นอกจากนี้อ็อบเจ็กต์ที่แสดงร่วมกันหรือโมดูลที่แสดงร่วมยังสามารถเข้าถึงสมาชิกคลาสได้อย่างเต็มที่รวมถึงส่วนตัวด้วย

วัตถุที่ใช้ร่วมกันเหมาะอย่างยิ่งสำหรับการห่อหุ้มสิ่งต่างๆเช่นวิธีการโรงงาน ตัวอย่างเช่นแทนที่จะต้องมีFooและFooFactoryทุกที่คุณสามารถมีคลาสที่มีอ็อบเจ็กต์ร่วมในความรับผิดชอบของโรงงาน


62

อ็อบเจ็กต์ Companion มีประโยชน์สำหรับการจัดเก็บสถานะและวิธีการที่ใช้ร่วมกันกับอินสแตนซ์ทั้งหมดของคลาสแต่ไม่ได้ใช้เมธอดหรือฟิลด์แบบคงที่ พวกเขาใช้วิธีการเสมือนปกติซึ่งสามารถถูกแทนที่ผ่านการสืบทอด สกาล่าไม่มีอะไรคงที่อย่างแท้จริง มีหลายวิธีที่คุณสามารถใช้ได้ แต่นี่คือตัวอย่างง่ายๆ

abstract class AnimalCounter
{
    var animals = 0

    def name: String

    def count()
    {
        animals += 1
        println("%d %ss created so far".format(animals, name))
    }
}

abstract class Animal
{
    def companion: AnimalCounter
    companion.count()
}

object Dog extends AnimalCounter
{
    val name = "dog"
}

class Dog extends Animal
{
    def companion = Dog
}

object Cat extends AnimalCounter
{
    val name = "cat"
}

class Cat extends Animal
{
    def companion = Cat
}

ซึ่งสร้างผลลัพธ์นี้:

scala> new Dog
1 dogs created so far

scala> new Cat
1 cats created so far

scala> new Dog
2 dogs created so far

scala> new Cat
2 cats created so far

1
ดูภาพประกอบที่คล้ายกันได้ที่นี่: daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik

30

... และเป็นสถานที่ที่ดีในการจัดเก็บวิธีการโรงงานแบบคงที่ (ไม่ใช่ DP) สำหรับคลาสที่มาพร้อมกัน หากคุณตั้งชื่อวิธีการโรงงานที่โอเวอร์โหลดเหล่านั้นให้ใช้ (/ ... /) คุณจะสามารถสร้าง / เริ่มต้นคลาสของคุณได้

  1. ไม่มี 'ใหม่' (ไม่สำคัญจริงๆ)

  2. ด้วยชุดพารามิเตอร์ที่เป็นไปได้ที่แตกต่างกัน (เปรียบเทียบกับสิ่งที่ Bloch เขียนใน Effective Java เกี่ยวกับตัวสร้างเหลื่อม)

  3. ด้วยความสามารถในการตัดสินใจว่าคุณต้องการสร้างคลาสที่สืบทอดมาใดแทนที่จะเป็นนามธรรม (มาพร้อมกับ)

รหัสตัวอย่าง:

abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
  def apply(s: String) = {
    new RealThing(s)
  }
  def apply(i: Int) = {
    new AlternativeThing(i)
  }
}

// somewhere else you can
val vs = AbstractClass("asdf")  // gives you the RealThing wrapped over string
val vi = AbstractClass(123)  // gives you AlternativeThing wrapped over int

ฉันจะไม่เรียก object / base class AbstractXxxxx เพราะมันดูไม่แย่: เหมือนกับการสร้างสิ่งที่เป็นนามธรรม ให้ชื่อเหล่านั้นมีความหมายที่แท้จริง พิจารณาใช้วิธีที่ไม่เปลี่ยนรูป, วิธีน้อย, คลาสเคสและปิดผนึกคลาสฐานนามธรรม


2
RealThingและAlternativeThingคลาสควรมีตัวprivateสร้างเพื่อบังคับให้ผู้ใช้ใช้AbstractClassโรงงานมี class AlternativeThing private(i: Int) extends AbstractClass
พบ

@ [Szymon Jachim] คลาสนามธรรมของ Scala ไม่สนับสนุนการสืบทอดหลายรายการ เหตุใดคอมไพเลอร์จึงอนุญาตในกรณีของคุณ?
user2441441

19

นอกเหนือจากสิ่งที่ Saem พูดในการตอบกลับของเขาคอมไพเลอร์ Scala ยังมองหาการแปลงโดยนัยประเภทในวัตถุที่แสดงร่วมที่เกี่ยวข้อง (ของแหล่งที่มาหรือเป้าหมาย) ดังนั้นจึงไม่จำเป็นต้องนำเข้าการแปลง

เกี่ยวกับเหตุผลของวัตถุเดี่ยวโดยทั่วไปการเขียนโปรแกรมใน Scalaกล่าวว่า:

ตามที่กล่าวไว้ในบทที่ 1 วิธีหนึ่งที่ Scala เป็นเชิงวัตถุมากกว่า Java คือคลาสใน Scala ไม่สามารถมีสมาชิกแบบคงที่ได้ สกาลามีวัตถุเดี่ยวแทน (น. 65)


3

ฉันมักจะเห็นวัตถุที่แสดงร่วมกันเป็นสะพานในการเขียนโค้ดทั้งเชิงฟังก์ชันและเชิงวัตถุใน Scala หลายครั้งเราต้องการฟังก์ชั่นบริสุทธิ์ที่รับอินพุตและให้ผลลัพธ์การประมวลผล การใส่ฟังก์ชั่นที่เกี่ยวข้องเหล่านั้นไว้ในวัตถุที่แสดงร่วมทำให้ง่ายต่อการค้นหาและใช้งานสำหรับตัวฉันเองรวมถึงสิ่งปลูกสร้างหนึ่งที่อยู่ด้านบนของโค้ดของฉัน

นอกจากนี้ยังเป็นภาษาที่มีให้เพื่อเขียนรูปแบบซิงเกิลตันโดยไม่ต้องทำอะไรเลย สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อคุณต้องการซิงเกิลตันเพื่อห่อหุ้มผู้แทนตลอดชีวิตของ JVM ตัวอย่างเช่นการเขียนไลบรารีไคลเอ็นต์ HTTP แบบง่ายใน Scala ซึ่งคุณสามารถห่อหุ้มตัวจัดการที่อิงกับการใช้งาน Java พื้นฐานและให้ผู้ใช้ API ของคุณอยู่ในโลกที่บริสุทธิ์


0

หากคุณกำหนดคลาสและอ็อบเจ็กต์ในไฟล์เดียวกันที่มีชื่อเดียวกันคลาสเหล่านั้นจะเรียกว่าคลาสและอ็อบเจ็กต์ที่แสดงร่วมกัน Scala ไม่มีคำหลักแบบคงที่เป็น JAVA คุณสามารถแทนที่แบบคงที่ด้วยคลาสที่แสดงร่วมและวัตถุใน Scala

สำหรับข้อมูลรายละเอียดเพิ่มเติมโปรดตรวจสอบคลาสบทความ และคีย์เวิร์ดออบเจ็กต์ในการเขียนโปรแกรมสกาล่า


-1

ในตอนแรกจะมีการแยกวิธีการแบบคงที่และวิธีการไม่คงที่อย่างชัดเจนนอกจากนี้ยังมีวิธีง่ายๆในการสร้างคลาสซิงเกิลตัน

นอกจากนี้ยังสามารถสืบทอดวิธีการจากคลาสและ / หรือลักษณะอื่นซึ่งไม่สามารถทำได้ด้วยวิธีการแบบคงที่ของ Java และสามารถส่งผ่านเป็นพารามิเตอร์ได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.