Restricted inheritance in java - java

I know that
class A { }
class B extends A { }
class C extends B { }
is completely legal and I can
C obj = new C();
obj.anyMethodfromA();
is possible.
Now question is this What if I don't want to access class A methods in class C only class B methods should be inherited.
Is this possible?
C anotherObj = new C();
anotherObj.anyMethodfromA(); //can be illegal?
anotherObj.anyMethodfromB(); //should be legal.

You cannot remove classA methods from classC, all you can do is override the classA method in classC and throw UnsupportedOperationException. like
class C extends B {
#override
public void someMethodWasInClassA() {
throw new UnsupportedOperationException("Meaningful message");
}
}

Restricting access for certain subclasses is not possible. You could use interfaces instead to add certain a functionality to a specific class in addition to inheritance.

You can use some sleight of hand using interface to hide the methodFromA but you cannot actually remove it.
class A {
public void methodFromA() {
System.out.println("methodFromA");
}
}
class B extends A {
public void methodFromB() {
System.out.println("methodFromB");
}
}
class C extends B {
}
interface D {
public void methodFromB();
}
class E extends B implements D {
}
public void test() {
// Your stuff.
C obj = new C();
obj.methodFromA();
// Make a D
D d = new E();
d.methodFromB();
// Not allowed.
d.methodFromA();
// Can get around it.
E e = (E) d;
e.methodFromA();
}

There is no such fine-grained inheritance in Java. Once you've marked A methods protected, that extends down the entire heirarchy.
A workaround would be to reimplement the class A methods in class C, throwing appropriate run-time exceptions. But you cannot enforce a compile time failure.
(Note that you could achieve what you want in C++ with friendships: you'd mark the methods private in class A and make class B a friend of class A.)

At the moment C is-a A, however it sounds like you don't want that. So rather than have that maybe C has-a B or B has-a A.
Prefer composition over inheritance.

Related

Inheritance in java(subclass of a subclass)

say we have three classes: class a , class b , class c;
class b inherits class a , if we define that class c inherits class b(which inherits class a) will the code give an error .If not the can we say that class c inherits class a;
in all i ask that can there be a subclass of a subclass??
In short, yes, you could definitely have a "chain" of inheritance. When you have a class A that inherits another class B, then it doesn't matter whether class B inherits from another class.
Though, you should keep in mind that a class is not able to inherit from multiple classes (it would throw a compiler error). Multiple inheritance in Java is achievable through the use of interfaces.
Yes, Multilevel inheritance refers to a mechanism where one can inherit from a derived class, thereby making this derived class the base class for the new class.
for example
Class A
{
public void methodA()
{
System.out.println("Class A method");
}
}
Class B extends A
{
public void methodB()
{
System.out.println("class B method");
}
}
Class C extends B
{
public void methodC()
{
System.out.println("class C method");
}
public static void main(String args[])
{
C obj = new C();
obj.methodA(); //calling grand parent class method
obj.methodB(); //calling parent class method
obj.methodC(); //calling local method
}
}

Interface hybrid inheritance does not throw error in java?

I have three interfaces A, B and C and one class D. B and C extend A and D implements B and C. Interface A has a default method called "does". I was expecting to have a compile-time error or run-time error, however, the program was executed without error.
Both B and C inherit from A. Shouldn't the compiler be confused as to which inherited method be called on D since D inherits two default methods one from C and one from B.
All of the three interfaces and the class are defined in separate files. I have placed the code sequentially in the code area below for demonstration.
public interface A {
default public void does(){
System.out.println("A");
}
}
public interface B extends A {
}
public interface C extends A {
}
public class D implements B, C {
}
public class Sample {
public static void main(String[] args) {
new D().does();
}
}

Trying to understand the basics of polymorphism in Java.

Can somebody please tell me if the keyword 'extends' must be an used (in the syntax) of child classes that overide methods of their super class.
The word extends is used to indicate for the whole class that this class is a sub-class of another class. It is not related to whether the sub-class overrides certain methods or not, that is entirely up to the sub-class class. The sub-class may decide to override none, some, or all of the methods of the super-class. The sub-class may override only methods which are not marked as final in the super-class.
Here is a somewhat trivial example:
class A {
// This is the super-class.
public void myMethod() {...};
}
class B extends A {
// This extends above says: B is sub-class of A.
// So this class B is the sub-class of A.
// You can override methods of A here, like this
public void myMethod() {...};
// but you're not required to override them.
}
Polymorphism in java is a concept by which we can perform a single action by different ways.it uses 2 concepts such as method overloading and method over riding.
A method is a set of code which is referred to by name and can be called (invoked) at any point in a program simply by utilising the method's name.
the method over riding concepts uses the key word 'extends'.
We can extend a class by using the extends keyword in a class declaration after the class name and before the parent class.
public class ParentClass {
}
and we define child class like
public class ChildClass extends ParentClass {
}
// example of extending a class
class B {
int x = 0;
void f1 () { x = x+1;}
}
class C extends B {}
public class Test1 {
public static void main(String[] args) {
B b = new B();
b.f1();
System.out.println( b.x ); // prints 1
}
}
// example of extending a class, overwriting a method
class B {
int x;
void setIt (int n) { x=n;}
void increase () { x=x+1;}
}
class C extends B {
void increase () { x=x+2;}
}
public class Test2 {
public static void main(String[] args) {
B b = new B();
b.setIt(2);
b.increase();
System.out.println( b.x ); // prints 3
C c = new C();
c.setIt(2);
c.increase();
System.out.println( c.x ); // prints 4
}
}

Enforcing interface implementation in order to use another class

SITUATION: Say there is a class A and an interface B.
REQUIREMENT: If any class, say C, wants to create objects of A and use them, then that class will also have to implement interface B.Is there any way to enforce this condition?
WHY: Now a question may arise as to why I want to do such a thing. The reason is that when a class C creates objects of A and uses them, then those objects call certain methods of C. I want to declare those methods in interface B, so that C will invariably implement those methods.
Try this snippet:
public interface B {
// methods
}
public class A {
private final B b;
public A(B b) {
this.b = b;
}
...
}
public class C implements B{
// implement B's methods
public static void main(String[] arg) {
C c = new C();
A a = new A(c);
}
}
Since you say that objects of class A will call methods on C, they will have to keep reference to C somehow. Make this reference of type B and you are done.
That is
public class A {
public A(B arg) {
....
}
}
Then in C:
A a = new A(this);
That will force class C to implement interface B.

Validating instances of inner-classes

I have a Java class B with an inner class C. Some methods of B accept an instance of C as parameter but I only want to accept C instances created by the proper instance of B. Is there a way to do this validation at compile time?
Example
C c1 = new C();
B foo = c1.getB(); // foo was created by instance c1
C c2 = new C();
c2.method(foo); // I want a compiler error here.
My case
Have a class names Map which hold a matrix of instances of the inner class MapArea. The nice thing about this scheme is that I can validate the xPos, and yPos fields at the constructor so no invalid Areas for a given map are built. The map as a method distanceFrom(MapArea startingPos, MapArea toLocation, MapArea... otherLocations) and I was trying to avoid to validate the map area arguments again.
If this is really the behavior you want, method() should really be defined in the inner class.
In other words, instead of:
public class C {
//...
public void method(B b) {
this.x = b.y;
//...
}
//...
public class B {
//...
}
//...
}
It should be:
public class C {
//...
public class B {
//...
public void method() {
C c = this.C;
c.x = this.y;
//...
}
//...
}
//...
}
Of course, this wouldn't solve the problem if, for example, you wanted public void method(B b1, B b2, B b3), where all three instances of B are enclosed by the same instance of C.
A compile error won't work, but you can at least throw an exception:
public class C
{
public static void main (String [] args)
{
C c1 = new C();
B b = c1.getB();
c1.useB(b); //OK
C c2 = new C();
c2.useB(b); //throws IllegalArgumentException
}
public B getB() { return new B(); }
public void useB(B b) {
if(b.getC() != this)
throw new IllegalArgumentException();
//...
}
private class B
{
public C getC() { return C.this; }
//...
}
}
There's no way (AFAIK) of doing this at compile time.
At runtime you can do it by having the outer instance's factory method pass a reference to itself to the inner instance's constructor.
The inner class would need to store that reference, such that the outer class can check whether it created that instance or not:
public class C {
public class B {
private C parent;
private B(C parent) {
this.parent = parent;
}
public C getParent() {
return parent;
}
}
public B getB() {
return new B(this);
}
public void method(B b) {
assert(this == b.getParent());
}
}
Actually, as Kip's concurrent answer shows, B can access C.this to get the parent object so there's no need to store the parent reference. However the method above would be necessary if C wasn't actually an inner class.
If you make the constructor of the inner class (C) private, I believe the enclosing class (B) can still instantiate it while other classes cannot. This ensures that only B and C can instantiate C.
Edit: I've verified that with a small mockup. Make the inner class constructor private, and then only the inner class (C) or the enclosing class (B) can instantiate it.
See http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc6.html for more. In particular: "Access protection never prevents a class from using any member of another class, as long as one encloses the other, or they are enclosed by a third class.".
There's no compile-time way to guard against instance-specific usage. Your best bet is probably throwing an Exception when the usage in incorrect. Another option you have is to have the parent class to have a Map of instances of the inner class, and to have other classes tell the outer class to operate on the inner class not by the instance but by some other references. This will work with other classes don't need to do anything directly with the inner class.

Categories