# Code Smell 286 - Overlapping Methods

> TL;DR: Avoid using private methods in parent classes with names that child classes can use.

# Problems

- The least surprise principle violation

- Unexpected behavior and [defects](https://maximilianocontieri.com/stop-calling-them-bugs)

- Hidden dependencies

- Limited extensibility

- Code ambiguity

- Open/Closed principle violation

- [Misleading design](https://maximilianocontieri.com/code-smell-58-yo-yo-problem)

# Solutions

1. Avoid [hierarchies](https://maximilianocontieri.com/code-smell-137-inheritance-tree-too-deep)
2. Rename private methods
3. Maintain clear naming
4. Avoid overlapping names
5. Avoid [protected methods](https://maximilianocontieri.com/code-smell-37-protected-attributes)
6. Subclassify for [essential relations](https://maximilianocontieri.com/code-smell-125-is-a-relationship). Not to [reuse code](https://maximilianocontieri.com/code-smell-11-subclassification-for-code-reuse)

# Context

When you use the same method name in parent and child classes, you create confusion.

A private method in the parent class cannot be overridden even if a public method with the same name exists in the child class. 

This is a problem most static languages have in their design

This disconnect leads to bugs and makes your code hard to maintain.

# Sample Code

## Wrong

<!-- [Gist Url](https://gist.github.com/mcsee/997cf467a1cd6ba3bfc8975b59ffb254) -->

```php
<?

class ParentClass {
    private function greet() {
        // This method is private
        return "Hello from ParentClass";
    }

    public function callGreet() {
        return $this->greet();
    }
}

class ChildClass extends ParentClass {
    public function greet() {
        // Overriding a concrete method is a code smell
        // Compilers SHOULD warn you
        return "Hello from ChildClass";
    }
}

$child = new ChildClass();
echo $child->callGreet();

// When callGreet() is invoked on the $child object,
// it executes the following:
// It calls $this->greet(), 
// which refers to the greet() method of ParentClass 
// because the original method is private 
// and cannot be overridden or accessed from ChildClass.

// The unexpected output is 'Hello from ParentClass'
```

## Right

<!-- [Gist Url](https://gist.github.com/mcsee/e1c8f52682b976200218c825430f9bac) -->

```php
<?

class ParentClass {
    protected function greet() {
        // notice the 'protected qualifier'
        return "Hello from ParentClass";
    }

    public function callGreet() {
        return $this->greet();
    }
}

class ChildClass extends ParentClass {
    public function greet() {
        return "Hello from ChildClass";
    }
}

$child = new ChildClass();
echo $child->callGreet();

// The output is "Hello from ChildClass"
// This is the standard (and wrong) solution
// Also fixed by most AIs
```

<!-- [Gist Url](https://gist.github.com/mcsee/002f5db2e8b139b15c2d2339da42bda0) -->

```php
<?

abstract class ParentClass {
    // Declare greet() as an abstract method
    // Following the template-method design pattern
    abstract protected function greet();

    public function callGreet() {
        return $this->greet();
    }
}

class ChildClass extends ParentClass {
    protected function greet() {
        return "Hello from ChildClass";
    }
}

class OtherChild extends ParentClass {
    protected function greet() {
        return "Hello from OtherChild";
    }
}

$child = new ChildClass();
echo $child->callGreet(); // Output: Hello from ChildClass

$otherChild = new OtherChild();
echo $otherChild->callGreet(); // Output: Hello from OtherChild
```                                                                               

# Detection

[X] Semi-Automatic 

You can detect this smell by looking for private methods in parent classes and checking if child classes define methods with the same name.

You must also test parent methods calling private methods.
 
# Tags

- Hierarchy

# Level

[X] Intermediate

# Why the Bijection Is Important 

Clear and predictable code should reflect the [real-world](https://maximilianocontieri.com/what-is-wrong-with-software) hierarchy it models.

When you use private methods with overlapping names, you create a [Bijection](https://maximilianocontieri.com/the-one-and-only-software-design-principle) gap between the model and the implementation. 

This gap confuses developers, increases defects, and violates clean code principles.

# AI Generation

AI generators often create this smell when they generate boilerplate parent-child relationships. 

They might not check access levels or consider inheritance implications.

# AI Detection

AI tools can fix this smell with clear instructions.

You can ask the AI to check for overlapping method names and refactor hierarchies.

## Try Them!

*Remember: AI Assistants make lots of mistakes*

| Without Proper Instructions    | With Specific Instructions |
| -------- | ------- |
| [ChatGPT](https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) | [ChatGPT](https://chat.openai.com/?q=correct+the+override+problem%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) |
| [Claude](https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) | [Claude](https://claude.ai/new?q=correct+the+override+problem%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) |
| [Perplexity](https://perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) | [Perplexity](https://perplexity.ai/?q=correct+the+override+problem%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) |
| [Copilot](https://www.bing.com/chat?showconv=1&sendquery=1&q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) | [Copilot](https://www.bing.com/chat?showconv=1&sendquery=1&q=correct+the+override+problem%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) |
| [Gemini](https://gemini.google.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) | [Gemini](https://gemini.google.com/?q=correct+the+override+problem%3A+%60%60%60javascript%0D%0Aclass+ParentClass+%7B%0D%0A++++private+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+This+method+is+private%0D%0A++++++++return+%22Hello+from+ParentClass%22%3B%0D%0A++++%7D%0D%0A%0D%0A++++public+function+callGreet%28%29+%7B%0D%0A++++++++return+%24this-%3Egreet%28%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0Aclass+ChildClass+extends+ParentClass+%7B%0D%0A++++public+function+greet%28%29+%7B%0D%0A++++++++%2F%2F+Overriding+a+method+is+a+code+smell%0D%0A++++++++return+%22Hello+from+ChildClass%22%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%0D%0A%24child+%3D+new+ChildClass%28%29%3B%0D%0Aecho+%24child-%3EcallGreet%28%29%3B%0D%0A%60%60%60) | 

# Conclusion

When designing parent and child classes, you should use methods that clearly define inheritance and accessibility. 

Avoid private methods that overlap with child methods.

This keeps your code readable, extensible, and aligned with clean code principles.

Languages like *Python* allow you to override parent methods regardless of their names, while *Java* strictly enforces access levels. 

*C#* behaves similarly to *Java*. 

These differences mean you need to understand the specific rules of the language you are working with to avoid unexpected behavior.

# Relations

%[https://maximilianocontieri.com/code-smell-137-inheritance-tree-too-deep]

%[https://maximilianocontieri.com/code-smell-58-yo-yo-problem]

%[https://maximilianocontieri.com/code-smell-11-subclassification-for-code-reuse]

%[https://maximilianocontieri.com/code-smell-125-is-a-relationship]

%[https://maximilianocontieri.com/code-smell-37-protected-attributes]
 
# Disclaimer

Code Smells are my [opinion](https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned).

# Credits

Photo by [Matt Artz](https://unsplash.com/@mattart) on [Unsplash](https://unsplash.com/photos/grayscale-of-seashell-against-black-background-h1AEAnu93P4)
        
* * *

> Inheritance is good, but you should never forget that it introduces tight coupling.

_Robert C. Martin_
 
%[https://maximilianocontieri.com/software-engineering-great-quotes]

* * *

This article is part of the CodeSmell Series.

%[https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code]
