What are the common standard exceptions in Scala?
I am especially interested in how is .Net's NotImplementedException equivalent called?
UPDATE: The answer about the NotImplementedException seems to be
org.apache.commons.lang.NotImplementedException
Almost nothing:
package scala {
final class MatchError(obj: Any) extends RuntimeException
final class UninitializedError extends RuntimeException("uninitialized value")
final case class UninitializedFieldError (msg: String) extends RuntimeException(msg)
package util.regex {
class SyntaxError(e: String) extends RuntimeException(e)
}
package xml {
class BrokenException() extends java.lang.Exception
case class MalformedAttributeException(msg: String) extends RuntimeException(msg)
package dtd {
case class ValidationException(e: String) extends Exception(e)
}
package include {
class CircularIncludeException(message: String) extends XIncludeException
class UnavailableResourceException(message: String) extends XIncludeException(message)
class XIncludeException(message: String) extends Exception(message)
}
package parsing {
case class FatalError(msg: String) extends java.lang.RuntimeException(msg)
}
}
}
The rest comes from Java, which cover pretty much all corners. It begs the question of what these Scala methods throw on other platforms, doesn't it?
The NotImplementedException is currently being considered for Scala 2.10, probably. See this thread.
You can just use whatever default already exists in Java. Scala doesn't really add anything to the standard exceptions in Java.
Related
When using JsonUtility to serialize in Unity, List of a class will be serialized as empty string if it's filled with subclasses of ExampleObjtype.
[Serializable]
public class SerializableGameEntityDebugSubclass : SerializableGameEntityDebug {
public SerializableGameEntityDebugSubclass() : base() {}
}
[Serializable]
public abstract class SerializableGameEntityDebug {
public string uuid = null;
public SerializableGameEntityDebug() {
this.uuid = "debuggin";
}
}
public class GameSaveData
{
public List<GameEntity.SerializableGameEntityDebugSubclass> serializableGameEntitiesDebug1 = new List<GameEntity.SerializableGameEntityDebugSubclass>{ new SerializableGameEntityDebugSubclass() };
public List<GameEntity.SerializableGameEntityDebug> serializableGameEntitiesDebug2 = new List<GameEntity.SerializableGameEntityDebug>{ new SerializableGameEntityDebugSubclass() };
}
serializableGameEntitiesDebug1 DOES get subclassed and serializableGameEntitiesDebug1 does NOT get subclassed. I find this very odd because even if I print out individually the serialized elements of the list, it works correctly in both cases.
There are two separate issues at play.
It seems JsonUtility won't serialize List of any abstract class no matter what. So the thing the list contains must not be an abstract class
When I change the abstract class to a regular class, it will serialize it, but it will only contain fields in the base class rather than child classes.
Therefore it seems the only workaround is to have many lists to serialize (one for each child class)
Update: A slightly more elegant solution was to switch from using JsonUtility to Json.net JsonConverter. This caused serialization to work perfectly, but not yet deserialization. I still had to write a converter class so the deserializer knows which class to instantiate. I followed this answer and it worked. Last but not least it seems that each serializable class needs to have a default empty constructor for the deserializer to call when trying to instantiate it before hydrating it, or else it might try to call other constructors with null args
I am working with the Upickle/Ujson and want to write a custom encoder to get the hang of things.
Suppose I have the following hierarchy (from the tutorial here: Link)
import upickle.default._
object TestDrive extends App {
sealed trait TypedFoo
object TypedFoo{
import upickle.default._
implicit val readWriter: ReadWriter[TypedFoo] = ReadWriter.merge(
macroRW[Bar], macroRW[Baz], macroRW[Quz]
)
case class Bar(i: Int) extends TypedFoo
case class Baz(s: String) extends TypedFoo
case class Quz(b: Boolean) extends TypedFoo
}
import TypedFoo._
println(writeJs(Bar(100)))
}
Firstly this fails to compile. Why is this the case? Have I misunderstood the page?
Secondly
What if I want to serialize Bar and add a field, "parent":"TypedFoo", at the same time? So Bar looks like:
{"parent":"TypedFoo", "$type":"package.TestDrive.TypedFoo.Bar","i":100}
How can I do this too?
Any way to serialize a Scala case class to JSON and have the ability to provide custom serialized names ?
For example, In Java this can be done using the Gson library :
public class SomeClassWithFields {
#SerializedName("name") private final String someField;
private final String someOtherField;
public SomeClassWithFields(String a, String b) {
this.someField = a;
this.someOtherField = b;
}
}
I tried doing this in Scala :
case class SomeClassWithFields(#SerializedName("name")
someField:String)
but it seems to have no effect .
Any thoughts ?
Yes it can be done. Here's how:
case class SomeClassWithFields(#(SerializedName #scala.annotation.meta.field)("name") someField:String)
The syntax is strange (note that the outer '#' wraps the "SerializedName" and the scala field annotation) but it works fine. See more details at: https://issues.scala-lang.org/plugins/servlet/mobile#issue/SI-8975
Further improving Corindiano's answer by making it into a custom annotation, which can be (re)used elsewhere.
import scala.annotation.meta.field
case class SomeClassWithFields(#SerializedNameField(value = "name") someField:String) { ... }
object SomeClassWithFields {
type SerializedNameField = com.google.gson.annotations.SerializedName #field
}
You can do it with spray-json calling the jsonFormat overloads.
Here's how it would work with your example:
import spray.json._
case class SomeClassWithFields( someField:String)
object SomeClassJsonProtocol extends DefaultJsonProtocol {
implicit val someClassFormat = jsonFormat(SomeClassWithFields,"name")
}
Suppose you have a Java method in a legacy library you need to use that takes a Class as an argument:
public void takeClass(Class<? extends JavaClass> cls);
Now, suppose you have a Ceylon class which extends JavaClass:
shared class CeylonClass() extends JavaClass() {}
Now, how can I use the method takeClass in Ceylon such that this works?
javaThing.takeClass( `class CeylonClass` );
// or maybe this should work?
javaThing.takeClass( javaClass<CeylonClass>() );
As shown above, I've been trying function javaClass in module ceylon.interop.java without success... if I do javaClass<JavaClass>() then it works, but this is no use for me, of course.
EDIT:
The error I get when using javaClass<CeylonClass>() as shown above:
argument must be assignable to parameter class of takeClass:
Class<CeylonClass> is not assignable to Class<JavaClass>?
Unfortunately, this is a case where you need to drop back to Java to add some glue. You can't, today, write it completely in Ceylon.
Explanation
The problem is that since Ceylon doesn't have use-site covariance, and since the Ceylon typechecker doesn't even understand Java's use-site covariance, the typechecker treats this method:
public void takeClass(Class<? extends JavaClass> cls);
As if it had this more restrictive signature:
public void takeClass(Class<JavaClass> cls);
Furthermore, the typechecker treats all Java classes as if they were invariant types.
Therefore, since javaClass<CeylonClass>() produces a Class<CeylonClass>, it's not considered assignable to the parameter of takeClass(). :-(
Workaround
The workaround is to add the following Java method:
public static <T extends JavaClass> void takeClass2(Class<T> cls) {
takeClass(cls);
}
Now this method can be called like this from Ceylon:
javaThing.takeClass2( javaClass<CeylonClass>() );
HTH
P.S.
While writing this up, I noticed that in fact java.lang.Class is actually a covariant type, and I think that Ceylon should easily be able to notice that too. So I created this issue:
https://github.com/ceylon/ceylon-compiler/issues/1474
I'd like to be able to use JUnit 4.7's ExpectedException #Rule in Scala. However, it doesn't seem to catch anything:
import org.junit._
class ExceptionsHappen {
#Rule
def thrown = rules.ExpectedException.none
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
This still fails with a NumberFormatException.
To make this work with JUnit 4.11 in Scala, you should meta-annotate your annotation so that the annotation is applied only to the (synthetic) getter method, not the underlying field:
import org.junit._
import scala.annotation.meta.getter
class ExceptionsHappen {
#(Rule #getter)
var thrown = rules.ExpectedException.none
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
EDIT: Following the release of JUnit 4.11, you can now annotate a method with #Rule.
You will use it like:
private TemporaryFolder folder = new TemporaryFolder();
#Rule
public TemporaryFolder getFolder() {
return folder;
}
For earlier versions of JUnit, see the answer below.
--
No, you can't use this directly from Scala. The field needs to be public and non-static. From
org.junit.Rule:
public #interface Rule: Annotates fields that contain rules. Such a field must be public, not static, and a subtype of TestRule.
You cannot declare a public fields in Scala. All fields are private, and made accessible by accessors. See the answer to this question.
As well as this, there is already an enhancement request for junit (still Open):
Extend rules to support #Rule public MethodRule someRule() { return new SomeRule(); }
The other option is that it non-public fields be allowed, but this has already been rejected: Allow #Rule annotation on non-public fields.
So your options are:
clone junit, and implement the first suggestion, the method, and submit a pull request
Extend the Scala class from a java class which implements the #Rule
-
public class ExpectedExceptionTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
}
and then inheriting from that:
class ExceptionsHappen extends ExpectedExceptionTest {
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
which works correctly.
As a very newbie to Scala I am just using a very simple workaround: explicitly catch the exception and fail if your expected exception is not thrown.
Below is a sample skeleton:
try {
*your code that should throw an exception*
fail("Did not generate *the.Exception.you.expect*")
} catch {
case t: *the.Exception.you.expect* => // do nothing, it's expected :)
}
Without knowing JUnit rules, and without testing it, because I don't have an appropriate setup at hand, I go out on a limb and suggest turning thrown into a val.
I guess its some member that is initialized with something and then it gets some state and then some other machinery checks the state against something. You are always creating new ones and keep forgetting the expectation.
If Scala has something similar like static imports, then catch-exception is an alternative to JUnit 4.7's ExpectedException #Rule.
I'm still using JUnit 4, and found #Juh_'s comment instructive. This worked in Scala 2.11.0.
import org.junit.rules.ExpectedException
import org.junit.{Rule, Test}
import scala.reflect.{ClassTag, classTag}
class DeleteMe {
object Thrower {
def throwException[R <: Throwable: ClassTag](message: String): Unit = {
throw classTag[R].runtimeClass.getConstructor(classOf[String]).newInstance(message).asInstanceOf[R]
}
}
#Rule
def exceptionRule:ExpectedException = ExpectedException.none()
#Test(expected = classOf[Exception])
def checkConversionExceptions = {
val myMessage = "My Message"
exceptionRule.expectMessage(myMessage)
Thrower.throwException[Exception](myMessage)
()
}
}