Non-static method cannot be referenced from a static context - methods

I'm trying to call a method from another class and from what I've gathered, the method I'm trying to call is an instance method. I've gathered that, that means it uses instance variables of an object. Is there an easy way to call this method?
This is the main method,
public void main()
{
Test.testPetOwner();
}
And this is the method I'm trying to call in a class called "Test"
public void testPetOwner()
{
String petName;
String species;
String hairCondition;
String posture;
testCompetitor();
PetOwner petOwner1 = new PetOwner();
System.out.println("What is the pet's name?");
petName = Genio.getString();
petOwner1.setPetName(petName);
System.out.println("What is the species of the pet?");
species = Genio.getString();
petOwner1.setSpecies(species);
System.out.println("What is the hair condition of the pet?");
hairCondition = Genio.getString();
petOwner1.setHairCondition(hairCondition);
System.out.println("How is the pet's posture?");
posture = Genio.getString();
petOwner1.setPosture(posture);
}

public void main()
{
Test t = new Test();
t.testPetOwner();
}

If we try to access an instance method from a static context , compiler has now way to guess which instance method ( variable for which object ), you are referring too. Though you can always access it using object reference.

Related

How to set a class wide variable?

Just starting with Swift, I'm creating an API service class but I don't understand how I can make this work!?!
import UIKit
class Hello {
var className: String
init() {
self.className = "hello"
}
class func someFunc() {
println(self.className = "hello") // <= This doesn't work
}
}
From what I understand, since I need someFunc to be accessible when I call it, I need it to have class func. Example, in my view controller, when the user clicks a button, I can do Hello.someFunc().
Thanks in advance for your help.
If you want to allow subclasses to be able to override it:
class var className: String { return "Hello" }
(Note that class variables cannot be stored properties; they must be computed properties.)
Otherwise:
static var className = "Hello"
(static is the same as final class)
You can read more about type properties in the Swift Programming Language book.
Your current println is failing because you're trying to print an assignment, rather than a string. I suspect you meant something more like:
println("ClassName is \"\(className)\"")
Although — having said all of that — if you just want to get the name of the class you ought to use:
println(self.dynamicType)
You would need to declared class variable as static that way, you can access it inside your class level methods using self. However, if you want to access that from instance method you will have to use class name with it.
class Hello {
static var className: String = ""
init() {
Hello.className = "hello"
}
class func someFunc() {
println(self.className = "hello")
}
}
Also notice that swift expects that the class variable are initialized when they are created.

How to use MethodCallExpression.Update

I'm trying and failing to use an ExpressionVisitor to modify an expression that calls a method. I have a SearchService that encapsulates the search logic and want to be able to amend the search arguments passed.
The class in which the SearchFunc should be modified and run:
public class SearchService
{
public Expression<Func<string, string, List<int>>> SearchFunc { get; set; }
public void Run()
{
SearchModifier modifier = new SearchModifier();
Expression<Func<string, string, List<int>>> newFunc = (Expression<Func<string, string, List<int>>>)modifier.Modify(SearchFunc);
}
}
SearchModifier is defined as:
public class SearchModifier : ExpressionVisitor
{
public Expression Modify(Expression expression)
{
return Visit(expression);
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
Debug.Print(string.Format("VisitMethodCall: {0}", node.ToString()));
//VisitMethodCall: value(ExpressionTree_test.MainWindow)._adminRepository.SearchUsers("orig val", "orig val2")
//trying to use the Update method to create an amended MethodCallExpression
List<ConstantExpression> newargs = new List<ConstantExpression>();
newargs.Add(Expression.Constant("my new arg 1", typeof(string)));
newargs.Add(Expression.Constant("my new arg 2", typeof(string)));
MethodCallExpression methodCallExpression = node.Update(node, newargs);
//causes exception
//Method 'System.Collections.Generic.List`1[System.Int32] SearchUsers(System.String, System.String)' declared
//on type 'ExpressionTree_test.AdminRepository' cannot be called
//with instance of type 'System.Collections.Generic.List`1[System.Int32]'
Debug.Print(string.Format("Amended VisitMethodCall: {0}", methodCallExpression.ToString()));
return base.VisitMethodCall(node);
}
The Run method is called like this:
_searchService = new SearchService();
_searchService.SearchFunc = (t, s) => _adminRepository.SearchUsers("orig val", "orig val2");
I can't find much information on using the MethodCallExpression.Update method so am not sure I'm doing this correctly. How to I change the values of the arguments in the method?
Of course there may be a better way of doing this and any suggestions gratefully received...
You're not using the result of the Update method. You should pass it to base.VisitMethodCall instead of node:
return base.VisitMethodCall(methodCallExpression);
EDIT
Sorry, I misread the question... The first argument to Update is not the expression node being visited, it's the instance on which the method is called. So the code should be:
node.Update(node.Object, newargs);

How do I correctly bind?

I have a class MyClass, which implements INotifyPropertyChanged, and it has some properties that must be bound in some page. In my page I have
private MyClass myclass;
and in the page constructor I write
ContentPanel.DataContext = myclass;
When I assign myclass to some MyClass object, which I get from some callback, nothing is shown in page.
But when I write the properties that I must change instead of MyClass class in page.cs and bind them it work correctly.
Or when I give
ContentPanel.DataContext = this;
and in xaml I write
{binding this.myclass.property}
it also works correctly.
Here is callback
public void GetCommonInfoCallback(UserCommonInfo userCommonInfo)
{
CommonInfo = userCommonInfo;
}
where UserCommonInfo is MyClass, and CommonInfo is myclass.
private UserCommonInfo userCommonInfo ;
public UserCommonInfo CommonInfo
{
get
{
return userCommonInfo;
}
set
{
if (userCommonInfo != value)
{
userCommonInfo = value;
OnPropertyChanged("CommonInfo");
}
}
}
I can't understand where is my mistake. Can you help me?
When you set DataContext, it is the specific instance of MyClass that is used for data binding. So after executing
ContentPanel.DataContext = myclass;
you could later execute
myclass.someProperty = "new value of someProperty";
and the data will be updated in the bound control (assuming this is not a OneTime binding, but OneWay or TwoWay binding instead).
If I understand you question correctly, you want to change the binding to use a different instance of MyClass.
myclass = new MyClass { /* ... */ }; // new instance of MyClass
At this point, the controls are still bound to the previous instance of MyClass. You can change that by updating the DataContext:
DataContext = myclass; // set context to the new MyClass instance
The second approach that you wrote, with
ContentPanel.DataContext = this;
represents a different style, where you are making the page class also serve as the data model instance for data binding.
In this case, you are not changing the data binding to use a new instance of the data model (the page instance, 'this', is not changing). IMHO, there is very valuable to separate the page and the data model, so I prefer to not use the DataContext = this approach.

How to understand this delegator

I'm reading the source of activejdbc, found these methods in ModelInstrumentation.
public void instrument(CtClass modelClass) throws Exception {
addDelegates(modelClass);
CtMethod m = CtNewMethod.make("public static String getClassName() { return \"" + modelClass.getName()
+ "\"; }", modelClass);
CtMethod getClassNameMethod = modelClass.getDeclaredMethod("getClassName");
modelClass.removeMethod(getClassNameMethod);
modelClass.addMethod(m);
}
CtClass modelClass = ClassPool.getDefault().get("org.javalite.activejdbc.Model");
private void addDelegates(CtClass target) throws NotFoundException, CannotCompileException {
CtMethod[] modelMethods = modelClass.getDeclaredMethods();
CtMethod[] targetMethods = target.getDeclaredMethods();
for (CtMethod method : modelMethods) {
if (Modifier.PRIVATE == method.getModifiers()) {
continue;
}
CtMethod newMethod = CtNewMethod.delegator(method, target);
if (!targetHasMethod(targetMethods, newMethod)) {
target.addMethod(newMethod);
} else {
System.out.println("Detected method: " + newMethod.getName() + ", skipping delegate.");
}
}
}
This class is used to enhance a model class, the first one instrument will firstly delegate all non-private methods from org.javalite.activejdbc.Model to its child model class, which means it will add such methods to the child:
public X f(...) {
return super.f(...);
}
I don't understand why it does this, since we can invoke these methods even if there is no delegates.
Explanation of this can be found in this discussion:
https://groups.google.com/forum/#!topic/activejdbc-group/l6KNBi5EPc0
Basically, the main problem is that the methods in the Model class that we need in a child class are static. Static classes in Java are not inherited. This means that when you do this:
Person.where(...)
You will be executing the method Model.where(), not the Person.where(), hence the framework would have no idea what table to query.
ActiveJDBC forces Model methods into child methods in order to at run time determine what table to go to for data.

How can I apply the "move method" refactoring with IntelliJ IDEA?

I want to be able to move an instance method from one class to another class ("Move method" from Fowler's "Refactoring") in IntelliJ IDEA. Unfortunately, when I try "Move..." (cmd: F6), it tells me that "There are no methods that have a reference type. Would you like to make method static and then move?" I do not want to make my method static, I want it to be an instance method on the other class instead.
My code example:
public class TheClass {
public void doStuff(){
int i = themethod();
}
private int theMethod() {
System.out.println( "Hello World!" );
return 0;
}
}
public class OtherClass {
}
Say I want to move theMethod from TheClass to OtherClass. Is there an automatic refactoring in IDEA for this, and if so: How do I apply it?
In IntelliJ 14-15 do the following:
Position the caret on theMethod().
press Ctrl/Cmd+F6 (Change signature).
Introduce new parameter: Type=TheOtherClass, Name=theOtherClass, Default value=new TheOtherClass()
Refactor
Then press F6 (move) and move the method to theOtherClass.
You will end up with:
public class TheClass {
public void doStuff() {
int i = new TheOtherClass().theMethod();
}
}
public class TheOtherClass {
int theMethod() {
System.out.println("Hello World!");
return 0;
}
}
The Move Method refactoring in IDEA only considers moving the method into classes related to it, i.e. used as its parameter or return value, or called from inside the method. Which is kinda logical: if the method has nothing concrete to do with the target class, why should it be there? OTOH I found this limiting in some cases where I still had a valid reason to move the method. So I had to do it by hand.
In intellij 13.1 (dont' know in previous version) it could be done with the
Choose Refactor | Extract | Delegate on the main menu
but there is a "strange" limit, apparently: it could be done only with a new freshly created class.
So you have to do apply this refactoring without creating the "OtherClass" (it will be create directly when you apply the refactoring).
So a real "move" of method on an alredy created class seems missing, quite strange behaviou
if theMethod() has nothing reference to the host class(TheClass), you can make this method static and then use "Move" command. After the method was moved to the target class, you should remove the static keyword.
There is another method. Imagine you have the code:
public int field;
public void foo(int a) {
assert field == a;
}
And you want to make foo static. Select the whole body of the method and preess Alt+Ctrl+M (Extract method). Type the same name of the method. Check "Declare static" checkbox (available only if the method only reads and doesn't modify the fields) and press Ok. So you get:
public void foo(int a) {
foo(a, field);
}
private static void foo(int a, int field) {
assert field == a;
}
Move static method wherever you want and use old foo's body to call it.

Resources