Scala'da Null / Nothing / Unit Kullanımı


95

Az önce okudum: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

Anladığım kadarıyla, Nullbu bir özellik ve tek örneği null.

Bir yöntem bir Null bağımsız değişken aldığında, ona yalnızca bir Nullbaşvuru veya nulldoğrudan iletebiliriz , ancak boş olsa bile ( nullString: String = nullörneğin) başka bir başvuru gönderemeyiz .

Bu Nullözelliği kullanmanın hangi durumlarda yararlı olabileceğini merak ediyorum . Ayrıca daha fazla örnek görmediğim Hiçlik özelliği de var.


Bir dönüş türü olarak Nothing ve Unit kullanmak arasındaki farkın ne olduğunu gerçekten anlamıyorum, çünkü her ikisi de herhangi bir sonuç döndürmüyor, örneğin loglama yapan bir yöntemim olduğunda hangisinin kullanılacağını nasıl bileceğim?


Birim / Boş / Hiç bir dönüş türünden başka bir şey olarak kullanımlarınız var mı?

Yanıtlar:


80

Hiçbir şeyi yalnızca yöntem asla geri dönmezse kullanırsınız (yani dönerek normal şekilde tamamlanamaz, bir istisna atabilir). Hiçbir şey asla somutlaştırılmaz ve tip sisteminin yararı için oradadır (James Iry'den alıntı yapmak gerekirse: "Scala'nın alt tip olmasının nedeni, tip parametrelerindeki varyansı ifade etme kabiliyetine bağlıdır." ). Bağlantı verdiğiniz makaleden:

Nothing'in diğer bir kullanımı, asla geri dönmeyen yöntemler için bir dönüş türüdür. Düşünürseniz mantıklı. Bir yöntemin dönüş türü Nothing ise ve kesinlikle Nothing örneği yoksa, böyle bir yöntem asla geri dönmemelidir.

Günlük tutma yönteminiz Birim döndürür. Gerçekte döndürülebilmesi için bir değer Birimi vardır. Gönderen API docs :

Unit, scala.AnyVal'ın bir alt türüdür. Unit, () türünde yalnızca tek bir değer vardır ve temel alınan çalışma zamanı sisteminde herhangi bir nesne tarafından temsil edilmez. Birim dönüş türüne sahip bir yöntem, geçersiz olarak bildirilen bir Java yöntemine benzer.


2
Teşekkürler, "asla geri dönmez" derken, aramanın süresiz olarak engellendiğini mi kastediyorsunuz (örneğin iş planlayıcısının başlangıç ​​yöntemi?)
Sebastien Lorber

3
@Sabastien: Normal olarak dönmez, bir istisna oluşturabilir (bkz. James-iry.blogspot.com/2009/08/… ). Engelleme çağrısı yalnızca bir istisna atma ile biterse, bu sayılır. soru için teşekkürler, bunun açıklığa kavuşturulması gerekiyordu.
Nathan Hughes

18

Alıntı yaptığınız makale yanıltıcı olabilir. NullTipi uyumluluk için orada Java sanal makine ve özellikle Java.

Scala'yı dikkate almalıyız :

  • tamamen nesne yönelimli: her değer bir nesnedir
  • kesinlikle yazılır: her değerin bir türü olmalıdır
  • nullJava kitaplıklarına ve koduna erişim için referansları işlemesi gerekir

bu nedenle null, Nullözellik olan ve nulltek örneği olan değer için bir tür tanımlamak gerekli hale gelir .

NullTip sistemi değilseniz veya derleyicide geliştirmediğiniz sürece , özellikle faydalı hiçbir şey yoktur . Özellikle Null, bir yöntem için bir tür parametresi tanımlamak için mantıklı bir neden göremiyorum , çünkünull


bu doğru, yani sonunda Null'un başka bir kullanımı yok mu?
Sebastien Lorber

@SebastienLorber cevabı düzenledi. Aslında ortalama bir geliştirici için herhangi bir kullanım göremiyorum. Belki başka biri faydalı bir şeyler düşünebilir.
pagoda_5b

Bunun için teşekkürler. Bu tür şeylerin nedenini bilirsek anlarız, yoksa hatırlarız.
Sreekar

Null, bir tür parametreniz olduğunda ve bu soru ve yanıtta olduğu gibi boş döndürmek isteyebilirsiniz , çünkü scala'da null kullanmaktan vazgeçtiğiniz için, nadiren ortaya çıksa da, tür sisteminde başka kullanımlar da olabilir
Daniel Carlsson

15

Birim / Boş / Hiç bir dönüş türünden başka bir şey olarak kullanımlarınız var mı?


Unit şu şekilde kullanılabilir:

def execute(code: => Unit):Unit = {
  // do something before
  code
  // do something after
}

Bu, yürütülecek rastgele bir kod bloğu geçirmenize izin verir.


Nullboş değer atanabilir herhangi bir değer için alt tür olarak kullanılabilir. Bir örnek şudur:

implicit def zeroNull[B >: Null] =
    new Zero[B] { def apply = null }

Nothing tanımında kullanılır None

object None extends Option[Nothing]

Bu, bir atamak için izin verir Noneher tür Optionçünkü Nothingherşey uzanır. '

val x:Option[String] = None

Tamam. Birim kullanımınız için, kod bloğunuz birimden başka bir şey döndürürse yürütmenin bu genel türü döndürebilmesi için genel bir tür kullanmış olabilirsiniz.
Sebastien Lorber

@Drexin'in başka bir cevaba yaptığı yorumda dediği gibi, çoğunlukla bir yan etkiyi belirtmek için kullanılır.
EECOLOR

6

kullanırsanız Nothingyapacak hiçbir şey yoktur (yazdırma konsolu dahil) bir şey yaparsanız çıktı türünü kullanınUnit

object Run extends App {
  //def sayHello(): Nothing = println("hello?")
  def sayHello(): Unit = println("hello?")
  sayHello()
}

... o zaman nasıl kullanılır Nothing?

trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]

1
Ayrıca, Eiçinde Optionbildirdiğinden konumda olmak zorundadır: trait Option[+E]izin vermek gibi şeylerval x: Option[Int] = None
vim

5

Aslında Nulltürü hiç kullanmadım Unit, ama java kullanacağınız yerde kullanıyorsunuz void. Nothingözel bir türdür, çünkü Nathan'ın da bahsettiği gibi, bunun hiçbir örneği olamaz Nothing. Nothingsözde alt türdür, yani başka herhangi bir türden bir alt türdür. Bu (ve kontravaryant tür parametresi), herhangi bir değeri Nil- ki bu a'dır - başına ekleyebilmenizin nedenidir List[Nothing]ve bu durumda liste bu öğe türünde olacaktır. Noneayrıca türden ise Option[Nothing]. Böyle bir kap içindeki değerlere her erişme girişimi, bir tür yönteminden geri dönmenin tek geçerli yolu olduğu için bir istisna atacaktır Nothing.


teşekkürler Hiçbirinin Seçeneği [Hiçbir Şey] genişletmediğini bilmiyordum. Bir alt tipin Hiçbir Şey kullanabileceği bazı genel kullanımlarda mantıklıdır (Sanırım Null ve Unit için bir örnek bulmak zor ...)
Sebastien Lorber

Ünite, yan etkilerin meydana geldiği yerlerde kullanılır, örneğin IO monad IO[Unit], konsola ve benzerine yazdırma için tipte olabilir .
drexin

Evet, IO monad'ı hiç kullanmadım, onu Unit ile kullanmak mantıklıdır (ve sonsuz bir akış üreten bir IO operasyonu ise belki hiç bir şey değil mi?)
Sebastien Lorber

Hayır, orada hiçbir şey anlam ifade etmiyor.
drexin

3

Hiçbir şey genellikle örtük olarak kullanılmaz. Aşağıdaki kodda, başka hüküm tipi olan Hiçbir şey Boolean bir alt sınıfını (yanı sıra başka AnyVal) 'dir. Bu nedenle, else cümlesi gerçekten hiçbir şey döndürmese de , tüm atama derleyici için geçerlidir .val b: Boolean = if (1 > 2) false else throw new RuntimeException("error")


1

İşte bir örnek Nothingdan scala.predef:

  def ??? : Nothing = throw new NotImplementedError

Tanıdık değilseniz (ve arama motorları üzerinde arama yapamıyorsanız) ???, Scala'nın henüz uygulanmamış herhangi bir şey için yer tutucu işlevidir. Tıpkı Kotlin'inki gibi TODO.

Sahte nesneler oluştururken aynı numarayı kullanabilirsiniz: kullanılmayan yöntemleri özel bir yöntemle geçersiz kılın notUsed. Kullanmamanın avantajı, ???asla uygulamak istemediğiniz şeyler için derleme uyarıları almayacağınızdır.


0

Kategori teorisi açısından Hiçbir şey bir başlangıç ​​nesnesi değildir ve Birim bir terminal nesnedir .

https://en.wikipedia.org/wiki/Initial_and_terminal_objects

Başlangıç nesneler olarak da adlandırılan ortak sonlu veya evrensel ve uç nesneler de denir nihai .

Bir konusu, her ikisi ise ilk ve , bir adlandırılır sıfır nesne ya da boş bir nesne.

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.