I'm looking over some open-source code and can't wrap my head around this snippet.
class Something
def self.smart
new.smart
end
def smart
"test"
end
end
class Other < Something
println Other.smart
Is the code trying to instantiate a new instance every time smart is called?
def self.smart
new.smart
end
is equivalent to static method, which can e accessed by using class name.
... static ... smart()
and
def smart
"test"
end
is equivalent to instance method, need object to access
... smart()
new is same as the in java, created an instance of class.
and the whole thing is equivalent to.
public static .... smart(){
new ClassName().smart();
}
Related
I want to load a resource in a top level function using Class.getResourceAsStream().
Is there any way to get a reference to the class that the top level function will be compiled into so that I can write, for example
val myThing = readFromStream(MYCLASS.getResourceAsStream(...))
Another way I found is to declare a local class or an anonymous object inside a top level function and to get its enclosingClass:
val topLevelClass = object{}.javaClass.enclosingClass
Note: to work, this declaration should be placed on top level or inside a top-level function.
Then you can use the topLevelClass as a Class<out Any>:
fun main(args: Array<String>) {
println(topLevelClass) // class MyFileNameKt
}
With Java 7 you can get a reference to the current Java class from a top level function using
MethodHandles.lookup().lookupClass()
No, there is no syntax to reference that class. You can access it using Class.forName(). For example, if the file is called "Hello.kt" and is located in the package "demo", you can obtain the class by calling Class.forName("demo.HelloKt").
In the absence of a way to get a reference directly, I've fallen back on creating an anonymous object in the current package
val myThing = object: Any() {}.javaClass.getResourceAsStream(...)
As linters like detekt would flag anonymous classes as EmptyClassBlock you could also use something like
internal object Resources
fun resourceStream(name: String): InputStream {
return Resources.javaClass.getResourceAsStream(name)
}
There have been some questions answered on this before.
How can I pass a scala object reference around in Java
How can I use a Scala singleton object in Java?
But my problem is that I have nested scala objects, something like:
object Criteria {
object ActionCriteria {
case class Action (parameter: String) {
def this(parameter: String) = { this(paramerter) }
}
object Action {
def apply(parameter: String): Action = { apply(parameter) }
}
}
}
In java I then need to create a list of Actions. I have tried this... to no avail:
import Criteria.ActionCriteria.Action$
....
List<Criteria.ActionCriteria.Action$.MODULE$> actions = new ArrayList<>();
As well as a bunch of other combinations like adding $.MODULE$ with every object. Right now I am getting the following error:
error: cannot find symbol Criteria.ActionCriteria
List<Criteria$ActionCriteria$Action> actions = new ArrayList<>();
Seems to work fine. Found this with Scala REPL:
scala> classOf[Criteria.ActionCriteria.Action]
res1: Class[Criteria.ActionCriteria.Action] = class Criteria$ActionCriteria$Action
If you want the type of Action object, not case class (highly unlikely, but for the sake of completeness):
scala> Criteria.ActionCriteria.Action.getClass
res2: Class[_ <: Criteria.ActionCriteria.Action.type] = class Criteria$ActionCriteria$Action$
The difference is caused by Scala expecting Action to be a type in classOf[Action], so it returns the type corresponding to the case class. When you use Action in a context where a value is expected, it returns the singleton instance instead, so you can call standard Java method getClass to get the type of object Action.
In case you need other types:
Criteria$ cm = Criteria$.MODULE$;
Criteria.ActionCriteria$ cacm = Criteria.ActionCriteria$.MODULE$;
Criteria$ActionCriteria$Action$ cacam = Criteria$ActionCriteria$Action$.MODULE$;
Criteria$ActionCriteria$Action caca = new Criteria$ActionCriteria$Action("Foo");
Criteria.ActionCriteria$ is breaking the pattern here. Why? According to Iulian Dragos' comment under bug SI-2034 this is a special case:
since objects are "the equivalent of static" in the Java world, we
wanted to make it easier for Java code to use static inner classes.
When there's only one level of nesting, there's a guaranteed
companion: every top-level object gets a mirror class (if there isn't
one) that creates static forwarders to module methods (that's how one
can run a main method defined inside an object). Therefore, a
special case for one-level nesting: those classes use the flattened
name (without a $ suffix) as outer_name. So, Java code can say new Outer.Inner.
Summary
For every level of nesting other than first you replace . with $ in your class names
If the target type is also an object you add $ at the end
If you want an instance you add .MODULE$
We are building a product that needs to run on production environments. We need to modify some of the functionality of a existing library. The existing library has class's and methods, we need to override 1 or more methods so that the caller uses our overriden methods instead of the original library.
OriginalLibrary
package com.original.library ;
public class OriginalLibrary {
public int getValue() {
return 1 ;
}
public int getAnotherValue() {
return 1 ;
}
}
Original Client
public class MyClient {
private OriginalLibraryClass originalLibraryObject ;
public MyClient () {
originalLibraryObject = new OriginalLibraryClass() ;
System.out.println(originalLibraryObject.getValue()) ;
System.out.println(originalLibraryObject.getAnotherValue()) ;
}
}
Output
1
2
Now, I need to change getValue() to return 3, instead of 1
Needed Output
3
2
package com.original.library.improved ;
public class OriginalLibrary extends com.original.library.OriginalLibrary {
public int getValue() {
return 3 ;
}
public int getAnotherValue() {
return super.getAnotherValue() ;
}
}
If I do the above, I need to tell my Original Client to reorder and use my new com.original.library.improved jar file before com.original.library.
I am almost convinced that this is the most non intrusive way to launch my improved services over and above the OriginalLibrary. I would have preferred a solution where I need to tell the customer to just add my jar file, no need to recompile, relink your client code.
Similar (not same) questions on a google search
here
here
java assist is excellent library for bytecode manipulation. I have modified code below as per your sample code given, You have to explore javaassist more for your actual requirenment
CtClass etype = ClassPool.getDefault().get("com.original.library.OriginalLibrary");
// get method from class
CtMethod cm = etype.getDeclaredMethod("getValue");
// change the method bosy
cm.setBody("return 3;");
etype.rebuildClassFile();
// give the path where classes is placed, In my eclipse it is bin
etype.writeFile("bin");
OriginalLibrary originalLibraryObject;
originalLibraryObject = new OriginalLibrary();
System.out.println(originalLibraryObject.getValue());
System.out.println(originalLibraryObject.getAnotherValue());
Now output of getValue is 3 because I changed body of that method.
A couple of questions -
How is the client getting an instance of your library's class?
If they are using new OriginalLibrary(), then you're pretty much stuck with creating a new subclass of OriginalLibrary and then asking your client to use your new OriginalLibraryImproved class. This is a common problem encountered in projects and is one reason why a library should not allow its clients to instantiate its classes directly using the new operator.
If instead, your client is instantiating OriginalLibrary using a factory method provided by the library (say, OriginalLibrary.getInstance()), you may want to check if there are any hooks into the factory that allow you to change the object being returned.
Do you have full control of the source code of the original library?
If yes, then you definitely should (and I cannot emphasize this strongly enough) provide factory methods for any class in the library that is instantiable. Doing this allows you to change the actual object being returned without modifying the client (as long as the returned object's class is a subclass of the return value from the factory method).
If not, then I suggest you do the following.
Create a subclass of OriginalLibrary (say, OriginalLibraryImproved).
Create a Factory class named OriginalLibraryFactory that has a static method named getInstance(). Write code to return an instance of OriginalLibraryImproved from this method.
Ask your client to replace all occurrences of new OriginalLibrary() with OriginalLibraryFactory.getInstance(). Note that this approach will only involve adding an extra import for the factory class. The client will still refer to the returned instance using the same OriginalLibrary reference as before.
The advantage of this approach is that it gives you complete flexibility to change the implementation details of OriginalLibraryImproved without affecting the client in anyway. You could also swap OriginalLibararyImproved with a newer version like OriginalLibraryImprovedVer2 and the client will be oblivious to the fact that it is using a new class. You'll just have to make sure that OriginalLibraryImprovedVer2 subclasses OriginalLibrary.
An even more flexible approach is to use the Wrapper or Decorator pattern to avoid the pitfalls of inheritance. You can understand more about the Decorator pattern here.
In a nutshell, try to avoid forcing your clients to use new and try to avoid inheritance unless you have very compelling reasons.
I have a Python file which contains a class. I need to create an instance of that class and be able to call methods in that through Java.
I came up with a solution like this:
PythonInterpreter r = new PythonInterpreter();
r.execfile("File.py");
PyObject p = r.eval("Car().begin()");
System.out.println(p.toString());
And the python code:
class Car(SomeExtendedClass):
myvar = 5
def set(self, my):
self.myvar = my;
def begin(self):
return self.myvar
Now, when I execute this, it prints 5 But if I run the following code:
PyObject p = r.eval("Car().begin()");
System.out.println(p.toString());
r.eval("Car().set(7)");
p = r.eval("Car().begin()");
System.out.println(p.toString());
It will still print 5, instead of 7
It looks like I did not create one instance of Car and it always creating a new instance instead of using the created one.
Am I right?
Is it possible to create a new instance from a class in a Python file, and invoke/get data from methods with Java?
I have tried loading PyInstance using eval() but I get cannot cast exception from it:
return (PyInstance) this.interpreter.eval(className);
I just found out the solution for this "mystery"
At first, we want to execute the python file we're going to get instances from:
r.execfile("File.py");
And then define the PyObject which will contain the class that you want to invoke:
PyObject car = r.get("Car");
And then you have to call the __call__ method in order to create a new instance of Car, and cast it to PyObjectDerived:
PyObjectDerived p = (PyObjectDerived) o.__call__();
Now you can invoke methods, like this:
Python code:
def set(self, my):
self.myvar = my;
Your java call:
p.invoke("set", Py.newInteger(5));
Hope I helped anyone.
Whenever you call Car() you create a new instance of the class. So this create a new object and calls its set method:
r.eval("Car().set(7)");
But this then creates another instance rather than manipulating the existing one:
p = r.eval("Car().begin()");
The call to r.eval("Car().begin()"); creates a new python object as you require, but it actually returns a reference to the python object containing the return value from the begin() method - not to the instance created. This isn't what you wanted.
Leaving the python class exactly as defined, this code gets a reference to a single instance of the class:
PyObject p = r.eval("Car()");
(As you already saw, an alternative is to omit the parenthesis which gets you a reference to the python class object, and then using __call__ on it to create an instance).
Then to call the method on the existing instance:
p.invoke("set", Py.newInteger(7));
To get at the modified value, since it is an attribute of the instance and is not available via a 'getter' method, the getattr method of the PyObject class can get to it (or you could add a get method to the python code):
System.out.println(p.__getattr__("myvar"));
It's a shame that once you get a reference to the object via p you can't just call the method on it with java syntax, but of course Java knows nothing of the methods and/or attributes available on the Python object and even if it did they could change at any time because of the dynamic nature of Python. So you're left with methods like invoke to bind Java/Python together.
This question already has answers here:
Can a class variable be an instance of the class?
(2 answers)
Closed 9 years ago.
Below is java code. I need to know the equivalent code in python:
class A {
public static A obj = new A();
}
You can't do this inside a python class definition, since the class has not yet been defined until the end of the class: block. You will have to set it after:
class A(object):
pass
A.obj = A()
You could do this with a metaclass:
class SelfReferencingObjectMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['obj'] = property(lambda self: self.__class__.obj)
return super(SelfReferencingObjectMetaclass, cls).__new__(cls, name, bases, attrs)
#property
def obj(cls):
try:
return cls._obj
except AttributeError:
cls._obj = cls()
return cls._obj
class A(object):
__metaclass__ = SelfReferencingObjectMetaclass
As #Daniel Roseman notes in the comments to #jamylak's answer though, there's probably an easier, more Pythonic way to solve the problem you have than this. Following that comment, how you would accomplish this functionally, if not identically in terms of the object structure, would be by having a module like this:
a.py
class A(object):
#property
def obj(self):
return a_inst
a_inst = A()
This does create the somewhat ugly construct from a import A in code that utilizes it, but it's a less complicated way to implement it.
Do you need this class member before any instance of the class is created? In not, you can try assigning it when the first instance is created:
class A (object):
obj = None
def __init__(self):
if A.obj is None:
a.obj = A()
# or:
a.obj = self
I think you'd like to do that because you're trying to implement a pattern like singleton or something like that.
You may read the following recipe from activestate: http://code.activestate.com/recipes/52558/
It explains the way it works and also shows some code.