How to Have Methods Inside Methods

Is it possible to have Methods inside Methods?

UPDATE: Since this answer seems to have gotten some interest lately, I wanted to point out that there is discussion on the Ruby issue tracker to remove the feature discussed here, namely to forbid having method definitions inside a method body.


No, Ruby doesn't have nested methods.

You can do something like this:

class Test1
def meth1
def meth2
puts "Yay"
end
meth2
end
end

Test1.new.meth1

But that is not a nested method. I repeat: Ruby does not have nested methods.

What this is, is a dynamic method definition. When you run meth1, the body of meth1 will be executed. The body just happens to define a method named meth2, which is why after running meth1 once, you can call meth2.

But where is meth2 defined? Well, it's obviously not defined as a nested method, since there are no nested methods in Ruby. It's defined as an instance method of Test1:

Test1.new.meth2
# Yay

Also, it will obviously be redefined every time you run meth1:

Test1.new.meth1
# Yay

Test1.new.meth1
# test1.rb:3: warning: method redefined; discarding old meth2
# test1.rb:3: warning: previous definition of meth2 was here
# Yay

In short: no, Ruby does not support nested methods.

Note also that in Ruby, method bodies cannot be closures, only block bodies can. This pretty much eliminates the major use case for nested methods, since even if Ruby supported nested methods, you couldn't use the outer method's variables in the nested method.


UPDATE CONTINUED: at a later stage, then, this syntax might be re-used for adding nested methods to Ruby, which would behave the way I described: they would be scoped to their containing method, i.e. invisible and inaccessible outside of their containing method body. And possibly, they would have access to their containing method's lexical scope. However, if you read the discussion I linked above, you can observe that matz is heavily against nested methods (but still for removing nested method definitions).

Calling a method inside another method in same class

Java implicitly assumes a reference to the current object for methods called like this. So

// Test2.java
public class Test2 {
public void testMethod() {
testMethod2();
}

// ...
}

Is exactly the same as

// Test2.java
public class Test2 {
public void testMethod() {
this.testMethod2();
}

// ...
}

I prefer the second version to make more clear what you want to do.

Method Within A Method

This answer was written before C# 7 came out. With C# 7 you can write local methods.

No, you can't do that. You could create a nested class:

public class ContainingClass
{
public static class NestedClass
{
public static void Method2()
{
}

public static void Method3()
{
}
}
}

You'd then call:

ContainingClass.NestedClass.Method2();

or

ContainingClass.NestedClass.Method3();

I wouldn't recommend this though. Usually it's a bad idea to have public nested types.

Can you tell us more about what you're trying to achieve? There may well be a better approach.

How to declare methods inside methods

You can use Extension Methods to achieve this.

Example:

public static class DataTableExtensionMethods
{
public static int ToDays(this DataTable dt)
{
// fetch and return the days.
}
}

Now you could call it with:

var myDays = Work.GetWork().ToDays();

Does C# have a concept of methods inside of methods?

I wouldn't worry so much about the restriction of access to a method on the method level but more class level, you can use private to restrict access of the method to that specific class.

Another alternative would be to use lambdas/anonymous methods, or if you're using C# 4.0, Action/Tasks to create them inside your method.

An example of an anonymous method using a delegate (C# 1/2/3/4) for your specific example (incl. I need an action that can take a string parameter and return a string?) would be something like this:

delegate string MyDelegate(string);

public void abc() {
// Your code..

MyDelegate d = delegate(string a) { return a + "whatever"; };
var str = d("hello");
}

.. using C# 3/4:

public void abc() {
// Your code..

Func<string, string> d = (a) => { return a + "whatever"; };
var str = d("hello");
}

.. using a more ideal solution through private method:

private string d(string a)
{
return a + "whatever";
}

public void abc()
{
// Your code..

var str = d("hello");
}

Based on your comment for another answer: I would just like to have this at the bottom of the method and then call it from some earlier code.

This won't be possible, you would need to define a variable for your method using either delegates or Actions and so it would need to be fully initialised by time you call it. You wouldn't then be able to define this at the bottom of your method. A much better option would be to simply create a new private method on your class and call that.

Where to put methods, inside parent or child components?

If only used among Child instances, I'd place the method in the Child class.

"whereas if it's in the child component, there are multiple identical methods that are retrieved."

The way you've declared doSomething() in child above does not make it an instance method.

The doSomething() method will end up property of the Child prototype & its reference will be shared by all instances.

For doSomething to end up an instance method you'd have to define something like this.doSomething = function(){... in the Child constructor.

(another exception is if you declare doSomething() a static method of the Child class' constructor).

Call method from method inside same class

You should be able to just add self to the method calls:

run = function() {
self$part_1()
self$part_2()
self$part_3()
}

I have two methods inside each other, how to return to parent from inner method

it tells me that the method's return type is void,

Yes, that's how most callbacks are defined. There is often no need to return, you instead act on the result.

I want to return the JSONObject response variable from the onResponse method to the parent postRequest method

Again, there's no need to return anything if you restructure the call. Plus, there was no return statement at the end of the method, so your code wasn't completely correct to start.

Use Volley to your advantage and pass around its Listener objects in order to "return things".

Sidenote This doesn't / shouldn't be an Activity class. If you need a Context, make a constructor.

public class JSONRequestService {

private final Context mContext; // TODO: Make constructor

final Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", error.getMessage());
};

// passthough a callback instead of returning
public void postRequest(Response.Listener<JSONObject> listener) {
CustomRequest jsonObjectRequest = new CustomRequest(Request.Method.GET, this.url, requestParameters, listener, errorListener);

// TODO: Add to request queue

}
}

Then, to use

JSONRequestService service = new JSONRequestService(getApplicationContext());
service.setParameters(Parameters);
service.postRequest(new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
// response is now available where you want
} catch (JSONException e) {
e.printStackTrace();
}
});

Now, as you can see, there's really not much difference between this approach and just making the Volley request directly. All you've done is expose the parameters and hide the URL, RequestQueue, and error listener behind another class.

I might even suggest using a Builder Pattern approach for the parameters because certainly each request uses different parameters.

public JSONRequestService withParameters(Map<String, String> Parameters) {
this.requestParameters = Parameters;
return this;
}

And now, you get to collapse the setter with the execution

JSONRequestService service = new JSONRequestService(getApplicationContext());

service.withParameters(Parameters).postRequest();

Using methods inside a constructor

Put behavior of object separately with creation:

public class Calculations {

private int number;
private int multiplier;
private String operator = "";

public Calculations(int number, String operator, int multiplier) {
this.number = number;
this.operator = operator;
this.multiplier = multiplier;
}

public int getNumber() {
return this.number;
}

public void setNumber(int number) {
this.number = number;
}

public int getMultiplier() {
return this.multiplier;
}

public void setMultiplier(int multiplier) {
this.multiplier = multiplier;
}

public String getOperator() {
return this.operator;
}

public void setOperator(String operator) {
this.operator = operator;
}

public void print() {
switch (getOperator()) {
case "+":
System.out.println(getNumber() + getMultiplier());
break;
case "-":
System.out.println(getNumber() - getMultiplier());
break;
case "*":
System.out.println(getNumber() * getMultiplier());
break;
case "/":
System.out.println(getNumber() / getMultiplier());
break;
case "%":
System.out.println(getNumber() % getMultiplier());
break;
default:
System.out.println("Something went wrong.");
}
}
}


Related Topics



Leave a reply



Submit