Suppose I have a super class that offers a public template method. Subclasses will have to implement some sub-operations. How do I declare this sub-ops to make sure they can only be called from SuperClass? There's protected, but that works the other way round as far as I know: Subclasses can access protected superclass members. I want to allow a superclasses (and only superclasses!) to call subclass members.
class SuperClass{
public:
void templateMethod(){
this->op1();
this->op2();
}
// how to declare these? public? protected?
virtual void op1() = 0;
virtual void op2() = 0;
}
class SubClass : public SuperClass{
// how to declare these? public? protected?
virtual void op1() { ... };
virtual void op2() { ... };
}
I'm currently working in C++ and Matlab, but I'd also be very interested in some general remarks considering other languages.
In C++, you can achieve your aim by making op1 and op2 private in all classes. This technique is idiomatic in C++.
A base class will access the private function in a child class through the v-table that is set up when an object is instantiated.
Of course, there is nothing stopping another function in your child class from calling a function marked private in that child class. If you want wanted to do that, then the child class would not be the correct place for the function.
The same can be said for Java, except, of course that virtual is automatic.
use "private" in both cases
A private method can be called from superclasses because Supercalss don't know about accessible of overrided methods in SubClass
class SuperClass{
public:
void templateMethod(){
op1();
op2();
}
private:
virtual void op1() = 0;
virtual void op2() = 0;
}
No need to write private, but it is nice to give some information at the interface.
class SubClass : public SuperClass{
virtual void op1() { ... };
virtual void op2() { ... };
}
is equal to
class SubClass : public SuperClass{
private:
virtual void op1() { ... };
virtual void op2() { ... };
}
Related
but I've been programming in Java so I know you can Override methods in Object's instantiation
private MyObject myObject=new MyObject(){
#Override
public void myMethod(int args){
.
.
.
}
}
can somebody show me how to do this in C# please.. Thanks
Unlike Java where all instance methods a virtual ones, in C# you have to put virtual keyword explicitly:
public class MyObject {
...
// in order to be overriden in a derived class, base method should be
// explictly declared as virtual or abstract
public virtual void myMethod(int args){
...
}
...
}
In C# override is a keyword as well, not just an attribute:
// class can't be declared locally, but explictly
public class MyOverridenObject: MyObject {
...
// override is a mandatory keyword in the context
public override void myMethod(int args){
...
}
}
Finally, C# doesn't allow implementing classes locally, so you have to declare the class explicitly (MyOverridenObject in the code above) and then use:
// Finally, you can assign an overriden class to the private field
private MyObject myObject = new MyOverridenObject();
so I know you can Override methods in Object's declaration
This isn't object declaration but class instantiation. And this feature doesn't exist in C# .
Therefore, you can only override polymorphic methods on class declarations:
public class A
{
public virtual void DoStuff() {}
}
public class B : A
{
public override void DoStuff() {}
}
Which access modifier, in an abstract class, do I have to use for a method,
so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?
public abstract class A {
??? void method();
}
public class B extends A {
#Override
public void method(){
// TODO
}
}
public class C extends B {
#Override
private void method(){
// TODO
}
}
I know that there will be a problem with static binding, if
someone calls:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
But maybe there is another way. How I can achieve that?
It is possible to relax the restriction, but not to make it more restrictive:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method(){ // OK
}
}
public class C extends A {
#Override
private void method(){ // not allowed
}
}
Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.
I would recommend using interfaces to selectively expose or hide the method:
public interface WithMethod {
// other methods
void method();
}
public interface WithoutMethod {
// other methods
// no 'method()'
}
public abstract class A {
protected void method();
}
public class B extends A implements WithMethod {
#Override
public void method(){
//TODO
}
}
public class C extends B implements WithoutMethod {
// no 'method()'
}
... then only work with the instances through the interfaces.
When overriding methods, you can only change the modifier to a wider one, not vice versa. For example this code would be valid:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method() { }
}
However, if you try to narrow down the visibility, you'd get a compile-time error:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
private void method() {}
}
For your case, I'd suggest to make C not implementing A, as A's abstraction implies that there's a non-private method():
public class C {
private void method(){
//TODO
}
}
Another option is to make the method() implementation in C throwing a RuntimeException:
public class C extends A {
#Override
public void method(){
throw new UnsupportedOperationException("C doesn't support callbacks to method()");
}
}
What you are asking for is not possible for very good reasons.
The Liskov substitution principle basically says: a class S is a subclass of another class T only then, when you can replace any occurrence of some "T object" with some "S object" - without noticing.
If you would allow that S is reducing a public method to private, then you can't do that any more. Because all of a sudden, that method that could be called while using some T ... isn't available any more to be called on S.
Long story short: inheritance is not something that simply falls out of the sky. It is a property of classes that you as the programmer are responsible for. In other words: inheritance means more than just writing down "class S extends T" in your source code!
This is impossible because of the polymorphism. Consider the following. You have the method in class A with some access modifier which is not private. Why not private? Because if it was private, then no other class could even know of its existence. So it has to be something else, and that something else must be accessible from somewhere.
Now let's suppose that you pass an instance of class C to somewhere. But you upcast it to A beforehand, and so you end up having this code somewhere:
void somewhereMethod(A instance) {
instance.method(); // Ouch! Calling a private method on class C.
}
One nice example how this got broken is QSaveFile in Qt. Unlike Java, C++ actually allows to lower access privileges. So they did just that, forbidding the close() method. What they ended up with is a QIODevice subclass that is not really a QIODevice any more. If you pass a pointer to QSaveFile to some method accepting QIODevice*, they can still call close() because it's public in QIODevice. They “fixed” this by making QSaveFile::close() (which is private) call abort(), so if you do something like that, your program immediately crashes. Not a very nice “solution”, but there is no better one. And it's just an example of bad OO design. That's why Java doesn't allow it.
Edit
Not that I missed that your class is abstract, but I also missed the fact that B extends C, not A. This way what you want to do is completely impossible. If the method is public in B, it will be public in all subclasses too. The only thing you can do is document that it shouldn't be called and maybe override it to throw UnsupportedOperationException. But that would lead to the same problems as with QSaveFile. Remember that users of your class may not even know that it's an instance of C so they won't even have a chance to read its documentation.
Overall it's just a very bad idea OO-wise. Perhaps you should ask another question about the exact problem you're trying to solve with this hierarchy, and maybe you'll get some decent advises on how to do it properly.
Here is a part of the #Override contract.
The answer is : there isn't any possibility to achieve what you have.
The access level cannot be more restrictive than the overridden
method's access level. For example: if the superclass method is
declared public then the overridding method in the sub class cannot be
either private or protected.
This is not a problem concerning abstract classes only but all classes and methods.
THEORY:
You have the determined modifiers order:
public <- protected <- default-access X<- private
When you override the method, you can increase, but not decrease the modifier level. For example,
public -> []
protected -> [public]
default-access -> [public, default-access]
private -> []
PRACTICE:
In your case, you cannot turn ??? into some modifier, because private is the lowest modifier and private class members are not inherited.
Consider following Java program:
abstract class Surprising
{
void fun()
{
System.out.println("fun() is invoked");
}
}
class myclass
{
public static void main(String args[])
{
Surprising s=new Surprising() { };
s.fun();
}
}
Here I am creating object of nameless subclass of my abstract class Surprising, not the object of abstract class because it isn't allowed to create object of abstract class in Java.
What is the equivalent C++ program? Is it possible to do this in C++? If yes, how & if no, why not allowed?
Lets say we have the class A:
class A
{
...
};
Now to create a derivative of it, we use e.g.
class B : public A
{
...
};
Now to create an object of an anonymous class we simply don't provide a class name:
class
{
...
} anon_object;
And finally we combine the two ways, inheritance and anonymous classes:
class : public A
{
...
} anon_a_derived_object;
In C++ the Surprising class would not be abstract, because it defines all of its members. If you want an abstract (i.e. not instantiable) class, make at least one of its members pure virtual. Like here:
class Surprising
{
public:
virtual void fun()=0;
};
You can then define the member in an anonymous class of which you create an instance and then invoke the newly defined member function on that instance:
#include <iostream>
int main()
{
class : public Surprising
{
public:
virtual void fun() { std::cout << "Surprise!" << std::endl; }
} inst_;
inst_.fun();
return 0;
}
You cannot do this as on-the-fly as in Java, in the sense of declaring the class as part of the new expression. But you can create a local class inside the function and use it:
void main(int argc, char **argv)
{
class MySurprising : public Surprising {};
MySurprising s;
}
There are several differences between Java and C++ relevant to this question. I tried to produce the C++ code that most closely matches the Java code in question.
#include <iostream>
class Surprising // class is abstract since it has pure virtual method
{
public:
virtual void fun() = 0; // pure virtual method makes the class abstract
};
// we can define the pure virtual method, but not in class
inline void Surprising::fun()
{
std::cout<<"fun() is invoked\n";
}
int main()
{
struct : Surprising // anonymous derived class
{
void fun() // we must provide an implementation of fun()
{ // for otherwise this class remains abstract and
Surprising::fun(); // cannot be instantinated
}
} s; // object of anyonmous class
s.fun();
}
I am new to C++, I coded in Java for an year. The equivalent in C++ for interfaces and abstract classes alike is only abstract classes. Is that supposed to be a handicap while doing factory design? There are many times I want to leave out the defining the methods to the inheriting classes and I want to enforce that.
If you define like this you can have what you want:
class A {
public:
virtual void pure_virtual(int param1) = 0;
virtual ~A() { };
};
EDIT: Thanks Nikolai and Mike!
Java interfaces are best translated as C++ abstract classes. In Java (as far as I know) a interface is merely a subset of an abstract class anyway, except it allows "multiple inheritance" which C++ has in all cases anyway.
class thing_interface {
public:
virtual ~thing_interface() {}
virtual void foo() =0; //pure virtual function
};
class other_interface {
public:
virtual ~other_interface () {}
virtual void bar() =0; //pure virtual function
};
class thing_impl : public thing_interface, public other_interface {
protected:
int member;
public:
thing_impl() : member(0) {}
virtual ~thing_impl() {};
virtual void foo() { std::cout << "FOO!\n";}
virtual void bar() { std::cout << "BAR!\n";}
};
The =0 syntax means it is not defined in the interface, but must be defined in classes that fulfill the interface. Also note that if you have any virtual function, you almost always want a virtual destructor as well. C++ will tell you an error if you try to make a thing_interface by itself, since there's no implementation functions.
It's not really a handicap, since I can't think of anything Java can do here that C++ can't.
In terms of interface/abstract classes you wont feel handicap. You should read about C++ pure virtual functions and abstract classes.
To have interface in C++, here is the sudo code:
class MyInterface {
virtual void func1() = 0;
virtual int func2(int x, int y) = 0;
}
class MyAnotherInterface {
virtual void func3() = 0;
virtual int func4(int x, int y) = 0;
}
To have abstract class in C++, here is the sudo code. You can see it only implements one function from the interface above. So you cannot create instance of it.
class MyAbstract : public MyIterface {
void func1() {
printf("in func1");
}
}
Now the actual concrete class:
class MyConcreteClass : public MyAbstract, public MyAnotherIterface {
int func2(int x, int y) {
printf("func2 x=%x,y=%y",x,y);
}
void func3() {
printf("in func3");
}
int func4(int x, int y) {
printf("func4 x=%x,y=%y",x,y);
}
}
There are some issues when you are using Multiple inheritance as I am using for MyConcreteClass. But if you only have one base with member variables and other base classes contain only pure virtual functions then this pattern acts exactly like Java, where the class containing some methods and member variables maps to extends and other classes which contain only pure virtual functions maps to `implements'.
In our example, Java equivalent code is
class MyConcreteClass extends MyAbstract implements MyAnotherInterface {
public int func2(int x, int y) {
System.out.print(String.format("func2 x=%x,y=%y",x,y));
}
public void func3() {
System.out.print("in func3");
}
public int func4(int x, int y) {
System.out.print(String.format("func4 x=%x,y=%y",x,y));
}
}
Where you feed handicap
The only other place where I feel handicap when coming from Java is generics. C++ has templates for that, but they some serious limitations.
class BaseClass {
private void f() {
System.out.println("Baseclass f()");
}
public static void main(String[] args) {
BaseClass dc = new DerivedClass();
dc.f();
}
}
class DerivedClass extends BaseClass {
public void f() {
System.out.println("DerivedClass f()");
}
}
In my opinion, the object dc refers to should have only one non-override method - public void f() method,which make it(the public method) invisible when refered to with BaseClass reference.Since the object dc referes to does not have the private void f() method either because the DeriverClass could not inherit the private method,how could the object dc refers to call method f()?
thanks.
A common(ish) misconception is that private is per instance rather than per class.
For example:
class Foo
{
private int a;
public bar(final Foo other)
{
other.a = 5;
}
}
Some people are under the impression that the code above should not work because "a" is "private". That is not the case, any Foo instance can access the private variables/methods of any other Foo instance. "private" just means that instances of other classes (other than Foo in this case) cannot access the private members.
Just to keep things straight, DerivedClass (DC) DOES inherit private void f() from BaseClass (BC). This inherited method is not accessible to DC but it is there because any method called in the BC part of DC has to have access to all of BC. So when you cast DC to a BC the inherited method becomes available. Now because you are running the code inside of the BC class it can access all of the private members of BC. If you moved the main to DC it shouldn't compile let alone run.
Four points:
(1) To elaborate on what vivyzer wrote, the code compiles because the main method in BaseClass has access to the class's own private methods. If you wrote the code as:
class BaseClass {
private void f() { }
}
class DerivedClass {
public void f() { }
}
class Bystander {
public static void main() {
BaseClass inst = new DerivedClass();
inst.f();
}
}
Then the code would not compile.
(2) This is allowed by the language to support the usecase where the author of a base class can add a new private method without worrying about other authors' derived types.
(3) You won't see this if the method was not private. If the base class's f() had package or protected visibility, then the method would be a virtual method.
(4) The reverse of point #2 is not supported by Java. Specifically, if a derived class has a private method, and a new version of the base type introduces a non-private method with the same signature, the derived class and new base class cannot be used together. There are other languages (for example C#) that addresses these sorts of modular, generational development questions more completely. If you are interested in this aspect, this is a good read on Artima: Versioning, Virtual, and Override
The main method is inside BaseClass and the private methods are visible to it. If main is in some other class, it will not compile.