Using Groovy's package name convention, I can intercept Groovy method calls to a Java method like so:
package groovy.runtime.metaclass.org.myGang.myPackage
class FooMetaClass extends groovy.lang.DelegatingMetaClass
{
FooMetaClass(MetaClass delegate)
{
super(delegate);
}
public Object getProperty(Object a, String key)
{
return a.someMethod(key)
}
}
This works fine if I really create an object of class Foo:
def myFoo = new Foo()
def fooProperty = myFoo.bar // metaclass invokes myFoo.someMethod("bar")
However what if Foo is an interface, and I want to intercept method calls to any implementation of it?
def myFoo = FooFactory.create() // I don't know what class this will be
fooProperty = myFoo.bar
Is there a way to achieve this without having a DelegatingMetaClass for every known implementation of the Interface?
You can create a class named "groovy.runtime.metaclass.CustomMetaClassCreationHandle" to globally handle metaclass creation process.
Inside this class, you can override this method:
protected MetaClass createNormalMetaClass(Class theClass, MetaClassRegistry registry) {
// if theClass instanceof Foo, return your special metaclass
// else return super.createNormalMetaClass(theClass, registry)
}
Related
Is there a way to invoke a function by default before any other function in a class is called?
I do not want to use frameworks and want to implement in pure Scala.
What I wanted to do is have some function in a class which checks if a user has access to the called method when a method of the same class is called.
This is done in a straightforward way with a private constructor, custom apply and companion object.
case class Foo private (bar: Bar){
def methYouWantToCall: Unit = ???
}
object Foo {
def apply(bar: Bar): Foo = {
val foo = new Foo(bar)
foo.methYouWantToCall
foo
}
}
Hence methYouWantToCall should be sideffecting function with Unit return type.
As you use scala, there are plenty of means of avoiding such ones.
I want to do something like this:
interface Serializable<FromType, ToType> {
fun serialize(): ToType
companion object {
abstract fun deserialize(serialized: ToType): FromType
}
}
or even this would work for me:
interface Serializable<ToType> {
fun serialize(): ToType
constructor(serialized: ToType)
}
but neither compiles. Is there a syntax for this, or will I be forced to use make this an interface for a factory? Or is there another answer? 😮 That'd be neat!
Basically, nothing in a companion object can be abstract or open (and thus be overridden), and there's no way to require the implementations' companion objects to have a method or to define/require a constructor in an interface.
A possible solution for you is to separate these two functions into two interfaces:
interface Serializable<ToType> {
fun serialize(): ToType
}
interface Deserializer<FromType, ToType> {
fun deserialize(serialized: ToType): FromType
}
This way, you will be able to implement the first interface in a class and make its companion object implement the other one:
class C: Serializable<String> {
override fun serialize(): String = "..."
companion object : Deserializer<C, String> {
override fun deserialize(serialized: String): C = C()
}
}
Also, there's a severe limitation that only a single generic specialization of a type can be used as a supertype, so this model of serializing through the interface implementation may turn out not scalable enough, not allowing multiple implementations with different ToTypes.
For future uses, it's also possible to give the child class to a function as a receiver parameter:
val encodableClass = EncodableClass("Some Value")
//The encode function is accessed like a member function on an instance
val stringRepresentation = encodableClass.encode()
//The decode function is accessed statically
val decodedClass = EncodableClass.decode(stringRepresentation)
interface Encodable<T> {
fun T.encode(): String
fun decode(stringRepresentation: String): T
}
class EncodableClass(private val someValue: String) {
// This is the remaining awkwardness,
// you have to give the containing class as a Type Parameter
// to its own Companion Object
companion object : Encodable<EncodableClass> {
override fun EncodableClass.encode(): String {
//You can access (private) fields here
return "This is a string representation of the class with value: $someValue"
}
override fun decode(stringRepresentation: String): EncodableClass {
return EncodableClass(stringRepresentation)
}
}
}
//You also have to import the encode function separately:
// import codingProtocol.EncodableClass.Companion.encode
This is the more optimal use case for me. Instead of one function in the instanced object and the other in the companion object like your example, we move both functions to the companion object and extend the instance.
Example:
object Test {
def test = {
doTest
}
protected def doTest = {
// do something
}
}
class MockTest extends WordSpec with Mockito{
"" in {
val t = spy(Test)
// how do i stub out doTest?
}
}
I have a Test class with a protected doTest method. How do I stub out this protected method?
I would advise to make doTest package private, so that clients of your object won't be able to call it, but you'll be able to test it from within the same package.
package com.company.my.foo
object Test {
def test = {
doTest
}
private[foo] def doTest = {
// do something
}
}
and
package com.company.my.foo
class MockTest extends WordSpec with Mockito{
"" in {
val t = spy(Test)
when(t.doTest()).thenReturn("foo")
}
}
Test is a singleton (all Scala objects are), you can subclass a class, but not an object. Hence protected is a bit meaningless here - you're saying this method should only be accessible to subclasses, but it's not possible to have any (since Test is an object).
You have a couple options depending on what is best suited to your needs. 1) you can make Test a class and then extend it, or 2) change the access level of doTest to public [which is the default in Scala if you don't specify an access modifier]
Could someone explain why scala would allow a public variable, to satisfy the implementation of an abstract declared Protected item? My first assumption is that the compiler would complain, but I created a small test to see if this worked, and to my surprise it does. Is there an advantage to this? (perhaps this is normal in OOP?) Any methods to avoid the accidental pitfall?
object NameConflict extends App {
abstract class A {
protected[this] var name:String
def speak = println(name)
}
class B(var name:String) extends A { //notice we've declared a public var
}
val t = new B("Tim")
t.speak
println(t.name) // name is exposed now?
}
It's normal and as in Java. Sometimes it's desirable to increase the visibility of a member.
You can't do it the other way around and turn down visibility in a subclass, because the member can by definition be accessed through the supertype.
If invoking a method has terrible consequences, keep the method private and use a template method that can be overridden; the default implementation would invoke the dangerous method.
abstract class A {
private[this] def dangerous = ???
final protected def process: Int = {
dangerous
template
}
protected def template: Int = ???
}
class B extends A {
override def template = 5
}
I've been curious about the impact of not having an explicit primary constructor in Scala, just the contents of the class body.
In particular, I suspect that the private or protected constructor pattern, that is, controlling construction through the companion object or another class or object's methods might not have an obvious implementation.
Am I wrong? If so, how is it done?
You can declare the default constructor as private/protected by inserting the appropriate keyword between the class name and the parameter list, like this:
class Foo private () {
/* class body goes here... */
}
Aleksander's answer is correct, but Programming in Scala offers an additional alternative:
sealed trait Foo {
// interface
}
object Foo {
def apply(...): Foo = // public constructor
private class FooImpl(...) extends Foo { ... } // real class
}