Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change method implementation in run-time using reflection?

Tags:

reflection

go

I have this type implementation:

type A struct{
  name string
}

func (a A) getName() string {
  return "My name is " + a.name 
}

How I can change implementation of method getName() for this type using reflection? For example, I want use next implementation instead of current:

func newGetName() string {
  return "test reflection"
} 
like image 874
Interloper Avatar asked Feb 18 '15 06:02

Interloper


People also ask

How can I change the behavior of a method in reflection?

Anyway, reflection does not allow you to change code behaviour, it can only explore current code, invoke methods and constuctors, change fields values, that kind of things. If you want to actually change the behaviour of a method you would have to use a bytecode manipulation library such as ASM.

What is reflectiontestutils in spring test context?

ReflectionTestUtils is a part of Spring Test Context framework. It is a collection for reflection-based utility methods used in a unit, and integration testing scenarios to set the non-public fields, invoke non-public methods, and inject dependencies.

What is reflectiontestutils in unit testing?

It is a collection for reflection-based utility methods used in a unit, and integration testing scenarios to set the non-public fields, invoke non-public methods, and inject dependencies. In this tutorial, we'll take a look at how we can use the ReflectionTestUtils in unit testing by going through several examples.

Is there a way to dynamically change a method at runtime?

There exists a couple of frameworks that allows you to dynamically change any method at runtime: Harmony Free and Open Source (MIT)! Prig: Free and Open Source (MIT), requires Visual Studio extension and running programs under a launcher, not updated since 2017.


2 Answers

Go is a compiled language. As such, it's not possible to modify the implementation of things at runtime. What you can do is changing the place function pointers point to:

var getName func(string) = func(name string) {
    return "my name is " + name
}

In order to make this work with a structure, you have to resort to a few tricks. First add getName as a member to A:

type A struct {
    name string
    getName func() string
}

Then we enclose a pointer to the structure as an implicit (i.e. closed over) parameter:

foo := &A{name: "Hans"}
foo.getName = func() string {
    return "my name is " + name
}

Now you can call A.getName() and the result is "my name is hans". You can use method expressions and many other features just fine, but getName is a structure member and not a method of A, so keep this in mind. When you want to give a new meaning to getName, assign something different to it:

foo.getName = func() string {
    return "test reflection"
}

Another idea that is especially applicable if you know in advance what implementations getName could have is to add a new member to A that says what implementation getName currently has and then switch over this variable.

like image 82
fuz Avatar answered Sep 19 '22 21:09

fuz


Note the idiomatic Go is to not do that and use interface instead:

See this example:

package main

import "fmt"

type Aer interface {
    getName() string
}

type A struct {
    name string
}

func (a A) getName() string {
    return "My name is " + a.name
}

type testA struct {
    a A
}

func (ta testA) getName() string {
    return "NEW: My name is " + ta.a.name
}
func main() {
    a := A{name: "nameA"}
    fmt.Println(a.getName())
    ta := testA{a: a}
    fmt.Println(ta.getName())
}

Output:

My name is nameA
NEW: My name is nameA
like image 41
VonC Avatar answered Sep 20 '22 21:09

VonC