Salam, Habr! Saya membawa Anda perhatian pada artikel Jumat pendek tentang Java, Scala, programmer gila dan janji-janji rusak.
Pengamatan sederhana terkadang menghasilkan pertanyaan yang tidak terlalu sederhana.
Di sini, misalnya, adalah fakta sederhana dan lahiriah, bahkan mungkin sepele yang menyatakan bahwa di Jawa Anda dapat memperluas kelas non-final dan antarmuka apa pun dalam cakupan. Dan yang lain, juga cukup sederhana, mengatakan bahwa kode Scala yang dikompilasi untuk JVM dapat digunakan dari kode Java.
Namun, kombinasi dari dua fakta ini membuat saya bertanya-tanya: bagaimana kelas mana pun akan berperilaku dari sudut pandang Jawa, yang dalam Scala disegel, yaitu: tidak dapat diperluas dengan kode eksternal relatif terhadap file sendiri?
Kelas Scala yang didekompilasi dalam pandangan artis. Sumber: https://specmahina.ru/wp-content/uploads/2018/08/razobrannaya-benzopila.jpg
Sebagai kelinci percobaan, saya mengambil kelas standar Option
. Dengan memasukkannya ke dekompiler yang ada di IntelliJ Idea, kita mendapatkan sesuatu seperti ini:
public abstract class Option
implements IterableOnce, Product, Serializable {
public abstract Object get();
}
Namun, kode yang didekompilasi tidak akan menjadi kode Java yang valid - masalah yang mirip dengan yang dijelaskan di sini , misalnya, dengan metode ini:
public List toList() {
return (List)(
this.isEmpty()
? scala.collection.immutable.Nil..MODULE$
: new colon(this.get(), scala.collection.immutable.Nil..MODULE$)
);
}
MODULE$ , package object. , , Java , ?
, , ...
Java ( Maven), Scala provided- β , , , :
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.13.1</version>
<scope>provided</scope>
</dependency>
, scala.Option
. Idea, , Scala , sealed-, , , :
package hack;
public class Hacking<T> extends scala.Option<T> {
@Override
public T get() {
return null;
}
public int productArity() {
return 0;
}
public Object productElement(int n) {
return null;
}
public boolean canEqual(Object that) {
return false;
}
}
- , Option Product.
, β . mvn package
β , , jar-, , Java, , , .
, Scala.
β¦ scala-
Scala (, SBT) β lib , , , ; build.sbt , Idea. ( ) :
import hack.Hacking
object Main {
def main(args: Array[String]): Unit = {
implicit val opt: Option[String] = new Hacking()
}
private def tryDo[T](action: => T): Unit = {
try {
println(action)
} catch {
case e: Throwable => println(e.toString)
}
}
}
implicit var
.
tryDo
β , : , , . call-by-name tryDo
, , .
, match
β , sealed class- ( , sealed-, ?)
object Main {
def main(args: Array[String]): Unit = {
tryMatch
}
private def tryDo[T](action: => T): Unit = {
}
private def tryMatch(implicit opt: Option[String]): Unit = tryDo {
opt match {
case Some(inner) => inner
case None => "None"
}
}
}
:
scala.MatchError: hack.Hacking
, : Option β sealed class, ( case Some case None), :
[warn] $PATH/Main.scala:22:5: match may not be exhaustive.
[warn] It would fail on the following input: None
[warn] opt match {
[warn] ^
, .
, - Option:
object Main {
def main(args: Array[String]): Unit = {
tryMap
}
private def tryDo[T](action: => T): Unit = {
}
private def tryMap(implicit opt: Option[String]): Unit =
tryDo(opt.map(_.length))
}
:
java.lang.NullPointerException
, map:
sealed abstract class Option[+A] /* extends ... */ {
final def isEmpty: Boolean = this eq None
def get: A
@inline final def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
}
, :
- β None. , isEmpty false.
- , this.get, null.
- null , β length.
- length null NPE.
, NPE , Java ? (, , , ...)
:
object Main {
def main(args: Array[String]): Unit = {
tryContainsNull
}
private def tryDo[T](action: => T): Unit = {
}
private def tryContainsNull(implicit opt: Option[String]): Unit =
tryDo(opt.contains(null))
}
(, , null) , contains -Nullable . , , , Option false β null. ?
:
true
, , , contains map: !isEmpty && this.get == elem
.
, . , null , Option ( , , ) else match.
Faktanya, semua yang dibutuhkan oleh artikel ini adalah percobaan kecil untuk mengungkapkan satu nuansa interaksi berbagai bahasa pada satu JVM. Nuansa, dengan sedikit pemikiran, jelas, tetapi - untuk selera saya, masih menarik.