Paket nesneleri


93

Paket nesneleri nelerdir, kavram değil, kullanımları nelerdir?

Çalışan bir örnek almaya çalıştım ve çalışmamın tek formu şuydu:

package object investigations {
    val PackageObjectVal = "A package object val"
}

package investigations {

    object PackageObjectTest {
        def main(args: Array[String]) {
            println("Referencing a package object val: " + PackageObjectVal)
        }
    }
}

Şimdiye kadar yaptığım gözlemler:

package object _root_ { ... }

izin verilmiyor (makul olan),

package object x.y { ... }

ayrıca izin verilmiyor.

Bir paket nesnesinin hemen üst pakette bildirilmesi gerektiği görülmektedir ve eğer yukarıdaki gibi yazılırsa, küme ayracı sınırlandırılmış paket bildirim formu gereklidir.

Ortak kullanımda mı? Öyleyse nasıl?



1
@Brent, bu harika bir kaynak, sadece paket nesnesi makalesi için değil. Yazarı duydum ama bu Scala turunu yazdığını fark etmedim, teşekkürler.
Don Mackenzie

Yanıtlar:


129

Normalde paket nesnenizi, package.scalakarşılık geldiği pakette çağrılan ayrı bir dosyaya koyarsınız . İç içe paket sözdizimini de kullanabilirsiniz, ancak bu oldukça sıra dışıdır.

Paket nesneleri için ana kullanım durumu, paket tarafından tanımlanan API'yi kullandığınızda paketinizin içinde ve paketin dışında çeşitli yerlerde tanımlara ihtiyaç duyduğunuz zamandır. İşte bir örnek:

// file: foo/bar/package.scala

package foo

package object bar {

  // package wide constants:
  def BarVersionString = "1.0"

  // or type aliases
  type StringMap[+T] = Map[String,T]

  // can be used to emulate a package wide import
  // especially useful when wrapping a Java API
  type DateTime = org.joda.time.DateTime

  type JList[T] = java.util.List[T]

  // Define implicits needed to effectively use your API:
  implicit def a2b(a: A): B = // ...

}

Artık bu paket nesnesinin içindeki tanımlar tüm paketin içinde mevcuttur foo.bar. Ayrıca, bu paketin dışındaki bir kişi ithalat yaptığında tanımlar içe aktarılır foo.bar._.

Bu şekilde, API istemcisinin kitaplığınızı etkin bir şekilde kullanmak için ek içe aktarmalar yapmasını gerektirmesini önleyebilirsiniz - örneğin, ölçeklendirmede yazmanız gerekir

import swing._
import Swing._

tüm iyiliğe onEDTve örtük dönüşümlere sahip Tuple2olmak Dimension.


13
Dikkatli olun: yöntem aşırı yükleme paket nesnelerinde çalışmaz.
retronym

Paket nesnesinin paket hiyerarşisinde bir seviye üstte tanımlanması gerektiğinin neden seçildiğini bana hatırlatıyor. Örneğin bu , kendi kök paketinize ait olmasını istiyorsanız, paket nesnenizle sanal orgveya comüst düzey paketi kirletmeniz gerektiği anlamına gelir org.foo. Tanımın doğrudan paketin altında olmasına izin vermenin bir parçası olması gerektiğini - biraz daha uygun dil api arayüzü olurdu.
matanster

Not yana Scala 2.10 az ve aşırı yük Yukarıdaki yapar paketi nesneler iş.
Jasper-M

58

Moritz'in cevabı yerinde olsa da, dikkat edilmesi gereken bir diğer husus, paket nesnelerin nesneler olmasıdır. Diğer şeylerin yanı sıra, bu, karma kalıtım kullanarak onları özelliklerden geliştirebileceğiniz anlamına gelir. Moritz'in örneği şu şekilde yazılabilir:

package object bar extends Versioning 
                          with JodaAliases 
                          with JavaAliases {

  // package wide constants:
  override val version = "1.0"

  // or type aliases
  type StringMap[+T] = Map[String,T]

  // Define implicits needed to effectively use your API:
  implicit def a2b(a: A): B = // ...

}

Burada Sürüm oluşturma, paket nesnesinin bir "sürüm" yöntemine sahip olması gerektiğini söyleyen soyut bir özelliktir, JodaAliases ve JavaAliases ise kullanışlı tür takma adları içeren somut özelliklerdir. Bu özelliklerin tümü, birçok farklı paket nesnesi tarafından yeniden kullanılabilir.


Bütün konu çok açılıyor ve başka bir zengin örnek için teşekkürler, tam potansiyeline alışmış gibi görünüyor.
Don Mackenzie

1
ancak vals olarak kullanılamazlar, bu yüzden gerçekten nesne değiller
Eduardo Pareja Tobes

7

@Alex Cruise, teşekkürler, bu ayrı bir derleme birimine ihtiyaç duyduklarını gösteriyor gibi görünüyor (belki de küme ayracı sınırlandırılmış paket kısıtlamasını aşıyor). Sorun şu ki, bunları nasıl kullanacağıma dair kendi varsayımım yerine sağlam bir kullanıcı tavsiyesi istiyorum.
Don Mackenzie

5

Paket nesneleri için ana kullanım durumu, paket tarafından tanımlanan API'yi kullandığınızda paketinizin içinde ve paketin dışında çeşitli yerlerde tanımlara ihtiyaç duyduğunuz zamandır.

Dotty temel alınarak 2020'nin ortalarında piyasaya sürülmesi planlanan Scala 3 için geçerli değil , burada olduğu gibi :

Üst Düzey Tanımlar

Üst seviyeye her türlü tanım yazılabilir.
Paket nesnelerine artık ihtiyaç yoktur, aşamalı olarak kaldırılacaktır.

package p 

type Labelled[T] = (String, T) 
val a: Labelled[Int] = ("count", 1) 
def b = a._2 
def hello(name: String) = println(i"hello, $name)

Teşekkürler @VonC, bu ve diğer birçok nedenden dolayı gerçekten Scala 3'ü bekliyorum. Paket nesnelerini pek kullanmadım ama üst düzey tanımları kullanacağımdan eminim.
Don Mackenzie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.