มีกรณีที่จำเป็นต้องใช้วัตถุร่วม (ซิงเกิลตัน) สำหรับคลาสหรือไม่? เหตุใดฉันจึงต้องการสร้างคลาสพูดFoo
และสร้างอ็อบเจ็กต์ที่แสดงร่วมด้วย
มีกรณีที่จำเป็นต้องใช้วัตถุร่วม (ซิงเกิลตัน) สำหรับคลาสหรือไม่? เหตุใดฉันจึงต้องการสร้างคลาสพูดFoo
และสร้างอ็อบเจ็กต์ที่แสดงร่วมด้วย
คำตอบ:
โดยพื้นฐานแล้ววัตถุที่แสดงร่วมจะเป็นสถานที่ที่สามารถวางเมธอดแบบ "คงที่" ได้ นอกจากนี้อ็อบเจ็กต์ที่แสดงร่วมกันหรือโมดูลที่แสดงร่วมยังสามารถเข้าถึงสมาชิกคลาสได้อย่างเต็มที่รวมถึงส่วนตัวด้วย
วัตถุที่ใช้ร่วมกันเหมาะอย่างยิ่งสำหรับการห่อหุ้มสิ่งต่างๆเช่นวิธีการโรงงาน ตัวอย่างเช่นแทนที่จะต้องมีFoo
และFooFactory
ทุกที่คุณสามารถมีคลาสที่มีอ็อบเจ็กต์ร่วมในความรับผิดชอบของโรงงาน
อ็อบเจ็กต์ 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
... และเป็นสถานที่ที่ดีในการจัดเก็บวิธีการโรงงานแบบคงที่ (ไม่ใช่ DP) สำหรับคลาสที่มาพร้อมกัน หากคุณตั้งชื่อวิธีการโรงงานที่โอเวอร์โหลดเหล่านั้นให้ใช้ (/ ... /) คุณจะสามารถสร้าง / เริ่มต้นคลาสของคุณได้
ไม่มี 'ใหม่' (ไม่สำคัญจริงๆ)
ด้วยชุดพารามิเตอร์ที่เป็นไปได้ที่แตกต่างกัน (เปรียบเทียบกับสิ่งที่ Bloch เขียนใน Effective Java เกี่ยวกับตัวสร้างเหลื่อม)
ด้วยความสามารถในการตัดสินใจว่าคุณต้องการสร้างคลาสที่สืบทอดมาใดแทนที่จะเป็นนามธรรม (มาพร้อมกับ)
รหัสตัวอย่าง:
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 เพราะมันดูไม่แย่: เหมือนกับการสร้างสิ่งที่เป็นนามธรรม ให้ชื่อเหล่านั้นมีความหมายที่แท้จริง พิจารณาใช้วิธีที่ไม่เปลี่ยนรูป, วิธีน้อย, คลาสเคสและปิดผนึกคลาสฐานนามธรรม
RealThing
และAlternativeThing
คลาสควรมีตัวprivate
สร้างเพื่อบังคับให้ผู้ใช้ใช้AbstractClass
โรงงานมี class AlternativeThing private(i: Int) extends AbstractClass
นอกเหนือจากสิ่งที่ Saem พูดในการตอบกลับของเขาคอมไพเลอร์ Scala ยังมองหาการแปลงโดยนัยประเภทในวัตถุที่แสดงร่วมที่เกี่ยวข้อง (ของแหล่งที่มาหรือเป้าหมาย) ดังนั้นจึงไม่จำเป็นต้องนำเข้าการแปลง
เกี่ยวกับเหตุผลของวัตถุเดี่ยวโดยทั่วไปการเขียนโปรแกรมใน Scalaกล่าวว่า:
ตามที่กล่าวไว้ในบทที่ 1 วิธีหนึ่งที่ Scala เป็นเชิงวัตถุมากกว่า Java คือคลาสใน Scala ไม่สามารถมีสมาชิกแบบคงที่ได้ สกาลามีวัตถุเดี่ยวแทน (น. 65)
ฉันมักจะเห็นวัตถุที่แสดงร่วมกันเป็นสะพานในการเขียนโค้ดทั้งเชิงฟังก์ชันและเชิงวัตถุใน Scala หลายครั้งเราต้องการฟังก์ชั่นบริสุทธิ์ที่รับอินพุตและให้ผลลัพธ์การประมวลผล การใส่ฟังก์ชั่นที่เกี่ยวข้องเหล่านั้นไว้ในวัตถุที่แสดงร่วมทำให้ง่ายต่อการค้นหาและใช้งานสำหรับตัวฉันเองรวมถึงสิ่งปลูกสร้างหนึ่งที่อยู่ด้านบนของโค้ดของฉัน
นอกจากนี้ยังเป็นภาษาที่มีให้เพื่อเขียนรูปแบบซิงเกิลตันโดยไม่ต้องทำอะไรเลย สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อคุณต้องการซิงเกิลตันเพื่อห่อหุ้มผู้แทนตลอดชีวิตของ JVM ตัวอย่างเช่นการเขียนไลบรารีไคลเอ็นต์ HTTP แบบง่ายใน Scala ซึ่งคุณสามารถห่อหุ้มตัวจัดการที่อิงกับการใช้งาน Java พื้นฐานและให้ผู้ใช้ API ของคุณอยู่ในโลกที่บริสุทธิ์
หากคุณกำหนดคลาสและอ็อบเจ็กต์ในไฟล์เดียวกันที่มีชื่อเดียวกันคลาสเหล่านั้นจะเรียกว่าคลาสและอ็อบเจ็กต์ที่แสดงร่วมกัน Scala ไม่มีคำหลักแบบคงที่เป็น JAVA คุณสามารถแทนที่แบบคงที่ด้วยคลาสที่แสดงร่วมและวัตถุใน Scala
สำหรับข้อมูลรายละเอียดเพิ่มเติมโปรดตรวจสอบคลาสบทความ และคีย์เวิร์ดออบเจ็กต์ในการเขียนโปรแกรมสกาล่า
ในตอนแรกจะมีการแยกวิธีการแบบคงที่และวิธีการไม่คงที่อย่างชัดเจนนอกจากนี้ยังมีวิธีง่ายๆในการสร้างคลาสซิงเกิลตัน
นอกจากนี้ยังสามารถสืบทอดวิธีการจากคลาสและ / หรือลักษณะอื่นซึ่งไม่สามารถทำได้ด้วยวิธีการแบบคงที่ของ Java และสามารถส่งผ่านเป็นพารามิเตอร์ได้