Don't inherit private member if it's accessed by public member - java

I'm sorry if this question may be asked all the time, but I searched and couldn't find an sufficient answer.
How to disable inheritance of private members/fields if they are being accessed by a public member/method?
So consider this:
public class A {
private MemberA a = new MemberA();
public void foo(TypeA x) {
a.methodCall(); //access to a
}
}
public class B extends A {
private MemberB b = new MemberB();
public void foo(TypeB x) {
b.methodCall();
}
}
If you hit the debugger you'll see, that B has a field a by type MemberA. That's in compliance with Java rules because if a public member has access to a private member it will be inherited.
But in B "a" is useless and only taking memory - even if you don't instanciate it in the constructor of B, because B calls it's super constructor and it has to be instanciated in A because a has very much use for a.
I need to have same method names for A and B and they have to be public, but since they do fundamentally different things but also share common logic B needs to be inherited from A.
So basically, I need to know how to overload and override a method the same time. Or duplicate code. What to do?

This situation -- where a class has data members that you do not want to inherit -- is called the "Refused Bequest" antipattern, and what it generally means is that your inheritance relationship is wrong. Rather than having B extend A, you need an interface C that both implement independently. If there is significant implementation that you do want to share, then perhaps you could introduce an abstract base class that A and B could share.

Alternatively, it could also be that MemberA and MemberB (not A and B) share the common interface (or abstract class), say "Member", including methodCall(). You could then do
public class A {
protected Member myMember; // sounds like an Austin Powers movie...
// in the constructor
myMember= new A();
}
while, in class B, the constructor does this instead: (or use DI, etc...)
myMember = new B();
and in foo(), which need not be overloaded, you call myMember.methodCall().
Without knowing your problem it's hard to say if this approach or #Ernest's is better. In either case you are looking for common functionality, and it will likely be the same amount of work.

Related

does inheritance violates the basic law of oops..?

let me first explain what i want to say actually
Suppose a class Sub inheriting the class Super.
now we can excess all no private members of class Super within class Sub. now Suppose the case
class Super{
private int id;
public int getId()
{
return id;
}
}
class Sub extends Super {
public static void main(String args[]){
Sub sub = new Sub();
System.out.println(sub.getId());
}
}
I know that creating Sub class object will call Super class constructor too.
But the job of constructor is to initialize the fields only -- not to allocate the memory to the object.
Moreover in case of abstract class where the initialization is not allowed we can still use the instance variable of abstract class.
The memory to instance variable will be assigned at time of instance creation only.
Than how can we use the instance fields without even creating the instance.
Doesn't it violets the oops concept..??
Please help over this. And thanks in advance.
I think you're confused about what happens when you use the extends keyword. What that keyword means is that a Sub is a more-specific kind of Super. By the Liskov Substitution Principle, all of the properties of Super must hold for Sub as well. That means that all of Super's private members (methods and properties) are present in an instance of Sub. It's just that for organizational reasons, the developer of Super decided that they didn't want any derived classes messing around with it directly.
Now, how does this relate to memory allocation? In the case of Java, you are correct that the constructor does not allocate memory. It just initializes the fields. The memory allocation is handled by the runtime, and it allocates enough for the whole picture. Remember, a Sub is a Super and then some. So it allocates enough memory to hold everything from the entire inheritance chain all the way back up through java.lang.Object.
abstract classes can, in fact be initialized, or even force their derived classes to initialize their members. For example:
public abstract class Super {
private int id;
public Super(int id) {
this.id = id;
}
public int getId() { return this.id; }
}
public class Sub extends Super {
public Sub() {
super(5); // failure to call this constructor is a compiler error
}
}
Now, because Sub can't see Super's private id field, it's free to declare a new one of its own. This does not override Super's field. Any of Super's methods that use that field will still use the one from Super. This could be a little confusing, so the best advice is don't think of it that way. Generally, you'll want to override methods not fields.
I totally agree with the answer of Ian. Totally. Regarding the title of your question,
Does inheritance violates the basic law of oops..?
the answer is it depends. There is a kind of inheritance that violates encapsulation principle: implementation inheritance.
You're using implementation inheritance every time you inherit (through extends primitive) from a class that is not marked as abstract. In that case, to know how to implement your subclass, you need to know the implementation (a.k.a. the code) of methods of the base class. When you override a method, you have to know exactly which is the behavior of that method in the base class. This kind of code reuse is often referred to as white-box reuse.
Quoting the GoF's book, Design Pattern:
Parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of its parent's implementation, it's often said that "inheritance breaks encapsulation".
So, to reduce implementation dependencies, you have to follow one of the principles of reusable object-oriented design, which is:
Program to an interface, not an implementation
inheritance only concern about what and how is accomplished, not what is promised. If you violate the promises of the base class, what will happen? is there any guarantee that makes you sure it's compatible? -even your compiler will not understand this mistake and you will face a bug in your codes. Such as:
class DoubleEndedQueue {
void insertFront(Node node){
// ...
// insert node infornt of queue
}
void insertEnd(Node node){
// ...
// insert a node at the end of queue
}
void deleteFront(Node node){
// ...
// delete the node infront of queue
}
void deleteEnd(Node node){
// ...
// delete the node at the end of queue
}
}
class Stack extends DoubleEndedQueue {
// ...
}
if the class wants to use inheritance with aim of code reuse, It may inherit a behavior that violates its principal, such as insertFront. Let's also see another code example:
public class DataHashSet extends HashSet {
private int addCount = 0;
public function DataHashSet(Collection collection) {
super(collection);
}
public function DataHashSet(int initCapacity, float loadFactor) {
super(initCapacity, loadFactor);
}
public boolean function add(Object object) {
addCount++;
return super.add(object);
}
public boolean function addAll(Collection collection) {
addCount += collection.size();
return super.addAll(collection);
}
public int function getAddCount(Object object) {
return addCount;
}
}
I just reimplement HashSet with DataHashSet class in order to keep track of inserts. In fact, DataHashSet inherit and is a subtype of HashSet. we can instead of HashSet just pass DataHashSet(in java is possible). Also, I do override some of the methods of the base class. Is this legitimate from Liskov substitution principle? As I do not make any changes in the behavior of base class just add a track to insert actions, It seems perfectly legitimate. But, I will argue this is obviously a risky inheritance and a buggy code. First, we should see what exactly add method do. add one unit to related property and call parent class method. There is a problem with that called yo-yo. Look at addAll method, first, it adds collection size to related property then call addAll in the parent, but what exactly parent addAll do? It will call add method several times(loop over the collection), which add will be called? the add in the current class, so, the size of count will be added twice. once when you call addAll and second when parent class will call add method in the child class, that's why we call it yo-yo problem. And another example, imagine:
class A {
void foo(){
...
this.bar();
...
}
void bar(){
...
}
}
class B extends A {
//override bar
void bar(){
...
}
}
class C {
void bazz(){
B b = new B();
// which bar would be called?
B.foo();
}
}
As you see in bazz method which bar will be called? the second one the bar in class B will be called. but, what is the problem here? the problem is foo method in class A will not know anything about the override of bar method in class B, Then your invariants may be violated. because foo may expect the only behavior of bar method that is in own class, not something is overridden. This problem is called fragile base-class problem.

Conflicting methods on interface multiple inheritance

I have the following interfaces (in Java, but it's more of an OO question, not language-specific, I'm interested in answers for any language)
public interface A {
int foo();
}
and
public interface B {
char foo();
}
If I now want to make the following class:
public class C implements A,B{
public int foo() {
return 0;
}
public char foo() {
return 0;
}
}
This won't compile because the methods are conflicting. Is there any way to make this work, or something with the same meaning (of course without modifying A or B, that would be trivial)?
No, the return type cannot be a deciding factor in making a method signature unique because you do not need to assign the returned value to anything, the compiler wouldn't know what to do in that case.
Concrete example:
...
C object = new C();
object.foo();
...
Which foo did I just call? Can't tell.
To make this work you'll need to have either different method names or different parameter types in the interface methods.
EDIT: assuming you have no control over the interfaces A and B (library classes or similar) this is the solution I'd take if I wanted to implement them in the same class:
public class C {
private objectA = new AImpl();
private objectB = new BImpl();
// Work with the objects here
private class AImpl implements A {
public int foo() {
// ...
}
}
private class BImpl implements B {
public char foo() {
// ...
}
}
}
The common solution is to give each method a different name. Avoid generic names that have a high chance of naming collision with another interface.
This problem is present because in OOP, is considered the existence of more one method with the same name but with different parameters and not by return type.
The problem is not the interface, the problem is the class.
Overloading comes with parameters.
There are several solutions to this problem in use. I am working on the assumption that these are independent interfaces, that the intention is multiple interface (implementation of two unrelated interfaces on the same object) and that overloading has nothing to do with it.
The solutions I am aware of are:
1. Scoping. A reference to foo() can be qualified as A.foo() or B.foo() to determine which is required.
1. Namespaces. The interfaces are inherited inside a namespace constructed for the purpose, and all references to foo() must be preceded by a namespace, eg A::foo(), B::foo().
1. Aliasing. One or both of the foo() methods are explicitly renamed when inherited. Calls become something like A_foo() and B_foo().
Ada certainly had a mechanism like this, and I think some variants of Pascal did too. I can find more examples if it's important.

Calling super class method inside implemented abstract method

Basicaly I have a need for several methods that do the same thing but with different parameters the sub-classes can chose from, and still force the implementation.
Is this a correct approach/design ?
EDIT: I have edited the addItem() body, these methods contain the final logic that is used to handle the passed parameters
public abstract Class A {
public abstract void addItemImpl()
addItem(String s) {
// do stuff
}
addItem(Collection c) {
// do stuff
}
addItem(Item item) {
// do stuff
}
}
public Class B extends A {
addItemImpl() {
addItem("text, text2")
}
}
public Class C extends A {
addItemImpl() {
addItem([item, item2])
}
}
No, this will not work.
You will not be able to define the "doStuff()" method because you have to handle the parameters. You provide not enough information to give you detailed help. But it's possible that generics might come in handy:
public abstract Class A<T> {
public addItem(T t) {
// dostuff with t
}
}
public Class B extends A<String> {
}
public Class C extends A<Collection> {
}
This is a perfect case for: Favor composition over inheritance.
Your subclasses don't fully benefit from the superclass and don't depend on its implementation details. Then define an interface for the contract B and C must obey (addItemImpl()) and compose them with A.
Ask yourself: is B really an A? is C really and A?
What you have is technically correct, but with out knowing what addItem actually does it is difficult to know if this is the best solution. My guess would be that there probably is a better way.
If addItem essentially set values to be used in the doStuff, I would just do that work in the Class B and C instead. Any others that need to do it the same way as B could extend it instead of A.
Edit: Based on your edit, I would say this is probably a bad example to use an abstract class. There is no truely shared functionality. An interface would be more appropriate as you need a different implementation for each. You are just trying to hide that inside an abstract class. I would change A to an interface along with using generics.
Only go the abstract class route if there is actually shared code that is exactly the same in all the classes without having to do any tricks to make it work (like above).
If you need force implementation for few methods, then Abstract methods are ideal.
But be careful only the very first Non-Abstract sub-class of the Super-class is bound to implement all the abstract methods in it....

why we turned to access superclass members although we can inherit them?

if we have 2 class Zoo & Moo as follows:
public class zoo {
String superString="super";
private String coolMethod(){
return "Zoo method";
}
}
public class Moo extends zoo{
public void useMyCoolMethod(){
zoo z=new zoo();
System.out.println(superString);//1
System.out.println(z.superString);//2
}
public static void main(String[]args){
new Moo().useMyCoolMethod();
}
}
at 1 & 2 we print the value of the String in the super class through inheritance and access, the question is , what is the benefit of Access although i can do the same thing by inheritance ? knowing that the Access approach isn't allowed if the two classes is in diff packages
By accessing through the object ref you are modifying the referenced object's state, by inheritance you are modifying the object you are currently in ( this reference ). So there is actually no benefit aside from encapsulation at class level and package level through out the access modifiers and that sort of thing, you just use it depending on the behavior you want for you're code, or in this case, how restrictive to modify the state of objects depending on the context.
But aside from that, i'm not sure if there is anything else.
Regarding your example there is no benefit at all in "access" the method, if you really wants to print "super" twice.
But normally OO programs contains more than two classes and the authors tries to modularize the code with defined interfaces (aka public methods or an API). Create modules with inheritance only is very hard and create clumsy code. So objects will need other instances and call there method by "access".
In line 1, you are using inheritance, i.e. you have a class animal and you have method move() which moves the animal using his four leg. But in case of Kangaroo, you want to use most of the feature of animal class but want to change how it moves based on the fact that it jumps and uses it hind leg for movement.
In Line 2, you are using composition, i.e. when you want to create car, you will need different component and they will interact with each other for that car to function. Here you can not inherit from GearBox or Engine but you have to use them as part of Car (or what you are calling access).
In the end its the relationship between Zoo and Moo will decide what method you want to use
Using this access and inheritance is same when you do Not want to modify the content of the inherited memeber..
eg:
public class A {
String s = "Hello";
}
public class B extends A{
String s = "Hi;
System.out.println(s); // Will print the s in class B
System.out.println(new A().s); // Will print the s in class A
}
Now as String s has no modifier, it is considered having Default modifier, that means it can be accessed by classes only with in its own package.
If you use protected access modifier, then you Need to extend the class and then use the inherited members, but you can Not use the protected member by creating an instance of the class that holds it and then use dot operator to access it, this will Not work..
eg :
package com.go;
public class A {
protected String s= "Hi";
}
package com.fo;
public class B extends A {
System.out.println(s); // This will work
A a = new A();
System.out.println(a.s); // This will NOT work
}
The access (default or package-private) would be useful if Moo was in the same package an didn't extend Zoo.
First of all, I think is a good practice to maintain class attributes with private visibility, and access them through getters and setters. In second place, you are not accessing the attribute by inheritance, you are creating an instance of Zoo, and accessing the superString attribute because of it package visibility, you could also access them from another class of the package that don't even extends Zoo class (and that's generally not a good thing) In third place, you don't need to create an instance of the super class to access his public or default attribute, you could simply do:
System.out.println(this.superString)
wich is absolutly the same as (if not local variable or parameter declared with the same name):
System.out.println(superString)
In conclusion, having default or public attributes, let client classes access them (read and write) without the class could do nothing about it, and this could bring side effects for the methods of the class that use those attributes.
Example 2 you have a separate instance of your zoo object, which is a bit weird, but since the method will always return the same thing there isn't much difference. If you changed your method to be based on constructor input or something you could see a difference in the 2.
public class zoo {
public String superString;
public zoo (String _superstring) {
superString = _superstring;
}
}
public class Moo extends zoo{
public void useMyCoolMethod(){
zoo z=new zoo("string1");
System.out.println(superString);//1
System.out.println(z.superString);//2
}
public Moo (String _superstring) {
superString = _superstring;
}
public static void main(String[]args){
new Moo("string2").useMyCoolMethod();
}
}
Will return
string2
string1

OOD: Code refactoring and best design (protected or getter/setter)

Reading the code for a project, I noticed this situation, there are two classes as the following example:
class A {
private class E aE;
private class F aF;
public A(){
aE = new E();
aF = new F();
}
public void foo1(){
aE.bar();
...
aF.poo();
}
}
class B implements Runnable {
private class E aE;
private class F aF;
public B(){
aE = new E();
aF = new F();
}
public void run(){
...
x = aE.bar()
...
}
}
I would refactoring this code in order to get a superclass A, but along this way it is better to make fields aE and aF protected in class A and use them in class B or add two methods in class A as getE() and getF() and use this method in class B ?
class B doesn't extend A, it appears to be a simple copy-paste job with the methods needed for implementing Runnable. You clearly should avoid that and make another class which sole purpose is running the application, you probably won't need class B after that.
Mark, From this example it is difficult to point out how you should refactor this code. Here are some possibilities -
Whether to have a common parent class for A and B depends upon whether there is an logical parent-child relationship between actual classes.
You can also extend class B from A if there is a relationship. You will have to expose aE and aF as public properties in that case.
Another possibility is you can implement Runnable on A itself, eliminating class B.
If it is very common to have both class E and F as private fields together, then you can consider encapsulating them in one type, say EF, and then compose other classes with that class.
However, the correct answer can be given only after knowing what the actual classes are.
Any statement about classes named 'A' and 'B' likely doesn't have enough context to be either wrong or right.
But I would, assuming a case in which it was reasonable to have a B extending A, almost always prefer to use protected or package-level data member access. If you have an interface that is formal and serious enough to use Get/Set accessors, you are probably outside the context in which implementation inheritance is a good design choice.

Categories