DEV Community

Talemul Islam
Talemul Islam

Posted on

πŸ”“ How to Call Protected Methods from Plugin Classes (PHP, Java, C#, Python)

πŸ” TL;DR β€” Protected methods aren’t meant to be accessed directly, but sometimes you must β€” for testing, plugin hooks, or legacy migrations. Here's how to do it (safely) in PHP, Java, C#, and Python.


πŸ€” What’s a Protected Method?

In Object-Oriented Programming, protected methods are only accessible from within the class or its subclasses.

So why break the rules?

  • πŸ§ͺ Unit testing inner logic
  • πŸ”Œ Plugin customization
  • πŸ› οΈ Legacy system debugging
  • πŸ” Data migration tasks

While it’s not best practice to poke around protected members, there are legitimate edge cases.


πŸš€ PHP β€” Using ReflectionMethod

class Plugin {
    protected function setup() {
        return 'initialized';
    }
}

$ref = new ReflectionMethod(Plugin::class, 'setup');
$ref->setAccessible(true);

$plugin = new Plugin();
echo $ref->invoke($plugin);  // initialized
Enter fullscreen mode Exit fullscreen mode

βœ… Helper Function

function callProtected($obj, $method, array $args = []) {
    $ref = new ReflectionMethod($obj, $method);
    $ref->setAccessible(true);
    return $ref->invokeArgs($obj, $args);
}
Enter fullscreen mode Exit fullscreen mode

β˜• Java β€” getDeclaredMethod + setAccessible(true)

class Plugin {
    protected void initialize() {
        System.out.println("Initialized!");
    }
}

Plugin plugin = new Plugin();
Method m = Plugin.class.getDeclaredMethod("initialize");
m.setAccessible(true);
m.invoke(plugin);  // Initialized!
Enter fullscreen mode Exit fullscreen mode

⚠️ In Java 9+, you may need:
--add-opens your.module/package=ALL-UNNAMED


πŸ§ͺ C# β€” Binding Flags to the Rescue

class Plugin {
    protected void Configure() => Console.WriteLine("Configured!");
}

var plugin = new Plugin();
var m = typeof(Plugin).GetMethod("Configure",
            BindingFlags.Instance | BindingFlags.NonPublic);
m.Invoke(plugin, null);  // Configured!
Enter fullscreen mode Exit fullscreen mode

🐍 Python β€” It’s Just a Convention

class Plugin:
    def _setup(self):
        return "initialized"

plugin = Plugin()
print(plugin._setup())  # initialized
Enter fullscreen mode Exit fullscreen mode

Python doesn’t enforce access levels like other languages β€” just don’t start the method with two underscores.


🧰 Laravel Example

Let's wrap PHP reflection in a clean Laravel helper:

// app/Helpers/ReflectionHelper.php
namespace App\Helpers;

class ReflectionHelper {
    public static function call(object $obj, string $method, array $params = []) {
        $ref = new \ReflectionMethod($obj, $method);
        $ref->setAccessible(true);
        return $ref->invokeArgs($obj, $params);
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

$discount = \App\Helpers\ReflectionHelper::call(
    $plugin,
    'calculateDiscount',
    [$user, $cart]
);
Enter fullscreen mode Exit fullscreen mode

πŸ›‘οΈ Should You Really Be Doing This?

Scenario Safe to Reflect?
Unit / integration testing βœ…
One-off migration tool βœ… (caution)
Production business logic ❌ Avoid
Public SDKs ❌ Avoid

πŸ“Œ If you must do this in prod: cache, guard, and document it clearly!


πŸ” Safe Reflection Practices

  • βœ… Wrap reflection in a utility class or trait.
  • βœ… Catch ReflectionException and fail gracefully.
  • βœ… Cache reflection metadata if used repeatedly.
  • πŸ“ Document clearly why reflection was used.

🧭 Quick Reference Table

Language Trick One-liner
PHP ReflectionMethod $m->setAccessible(true)
Java Method#setAccessible() m.invoke(obj)
C# BindingFlags.NonPublic mi.Invoke(obj, null)
Python Convention only obj._method()

🧠 Final Thoughts

Reflection is a power tool β€” like a chainsaw in the hands of a surgeon.

Use it when:

  • πŸ” Testing internals
  • πŸ”§ Fixing legacy systems
  • 🧩 Customizing closed-source plugins

Don’t use it when:

  • ❗ Building production-critical logic
  • πŸ”“ Bypassing encapsulation carelessly

πŸ’¬ Have Questions or Stories?

Have you ever had to β€œcrack open” a class to call a protected method?

Got bitten by an API update that broke your reflection hack?

Drop your thoughts and stories in the comments below πŸ‘‡


πŸ“Œ If this helped you, consider following me for more backend, Laravel, and low-level tricks.

⚠️ ⚠️ Important Note:
Do NOT use this in production business logic!
Using reflection to bypass protected methods can lead to:

πŸ”₯ Code that breaks silently after plugin/library updates

πŸ› Fragile systems that are hard to maintain or debug

πŸ”“ Violations of encapsulation and OOP design principles

🚫 Unintended side effects or security risks

Top comments (1)

Collapse
 
xwero profile image
david duymelinck

Never do this with reflection!
If you want to expose a protected method use a child class.

If you want to test a protected method, you are creating the wrong tests.
In any other case make the method public.

Use object visibility as intended, and you don't need a list of warnings.