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.
Related
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() { ... };
}
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 was going over the official Oracle tutorial where it introduces the idea of polymorphism with the example of a class hierarchy of 3 classes; Bicycle being the superclass, and MountainBike and RoadBike being 2 subclasses.
It shows how the 2 subclasses override a method "printDescription" declared in Bicycle, by declaring different versions of it.
And finally, toward the end, the tutorial mentions the Java Virtual Machine (JVM) calls the appropriate method for the object that is referred to in each variable.
But, nowhere does the tutorial on polymorphism mention the concept of "abstract" classes and methods. How is run-time polymorphism achieved unless printDescription() in Bicycle is declared "abstract"? I mean, given this example, based on what hints does the compiler decide not to bind method invocation to the reference type at compile time, and think that it should leave it for the JVM to deal with at run-time?
Below is the example used:
public class Bicycle {
public int cadence;
public int gear;
public int speed;
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
public void printDescription(){
System.out.println("\nBike is " + "in gear " + this.gear
+ " with a cadence of " + this.cadence +
" and travelling at a speed of " + this.speed + ". ");
}
}
public class MountainBike extends Bicycle {
private String suspension;
public MountainBike(
int startCadence,
int startSpeed,
int startGear,
String suspensionType){
super(startCadence,
startSpeed,
startGear);
this.setSuspension(suspensionType);
}
public String getSuspension(){
return this.suspension;
}
public void setSuspension(String suspensionType) {
this.suspension = suspensionType;
}
public void printDescription() {
super.printDescription();
System.out.println("The " + "MountainBike has a" +
getSuspension() + " suspension.");
}
}
public class RoadBike extends Bicycle{
private int tireWidth;
public RoadBike(int startCadence,
int startSpeed,
int startGear,
int newTireWidth){
super(startCadence,
startSpeed,
startGear);
this.setTireWidth(newTireWidth);
}
public int getTireWidth(){
return this.tireWidth;
}
public void setTireWidth(int newTireWidth){
this.tireWidth = newTireWidth;
}
public void printDescription(){
super.printDescription();
System.out.println("The RoadBike"
" has " + getTireWidth() +
" MM tires.");
}
}
public class TestBikes {
public static void main(String[] args){
Bicycle bike01, bike02, bike03;
bike01 = new Bicycle(20, 10, 1);
bike02 = new MountainBike(20, 10, 5, "Dual");
bike03 = new RoadBike(40, 20, 8, 23);
bike01.printDescription();
bike02.printDescription();
bike03.printDescription();
}
}
How is run-time polymorphism achieved unless printDescription() in
Bicycle is declared "abstract"?
Why would you think abstract classes would change anything? Abstract classes do 2 primary things
Allow the programmer to declare a class that cannot itself be instantiated, forcing subclassing, and
Allow the programmer to force subclasses to provide implementations of methods, by declaring the method abstract.
Note that point 2 does not imply that polymorphism won't work unless a method is declared abstract on the base class; rather, it provides the developer an opportunity to force a subclass to provide an implementation, which is not required in subclassing scenarios that don't involve any abstract usage.
That's it. In other words, the notion of abstract compliments Java's polymorphism -- it is a language feature, but doesn't have anything to do with the dynamic dispatch Java uses at runtime to invoke methods. Anytime a method is invoked on an instance, the type of the instance at runtime is used to determine which method implementation to use.
virtual is a keyword in many languages that means "this method can be overridden by a subclass". Java does not have that keyword but instead all non static member methods are virtual and possible to override.
abstract is the same as virtual, except it tells the compiler that the base class does not have a definition for the method. It's useful at times if there is no useful function for the base class to perform, but it's by no means needed to be able to override the base class method.
In your case, the printDescription method has a useful definition for the base class, so there's no need to declare it abstract. It's virtual by default and therefor overridable by the subclass, so there is no need for a keyword to indicate that.
In Java all methods are bind at run-time (that's what you can achieve in C++ declaring a method virtual).
So the JVM can always dispatch the method correctly.
Actually the method binding in Java could never be static, because you are always dealing with references to objects (can't allocate an object on the stack, like C++).
This actually force the JVM to always check the run-time type of an object reference.
There no need to declare that method abstract.. In runtime polymorphism, appropriate derived class method is invoked based on what class instance does the base class reference points to..
Consider the following example: -
class A {
public void doSomething() {
}
}
class B extends A {
public void doSomething() {
System.out.println("In B")
}
}
public class Test {
public static void main(String args[]) {
A obj = new B(); // Base class reference and derived class object.
obj.doSomething(); // Calls derived class B's method and prints `In B`
}
}
To quote the statement that you read: -
the tutorial mentions the Java Virtual Machine (JVM) calls the
appropriate method for the object that is referred to in each
variable.
To justify the above statement, see the above example. There your B class method is invoked because your base class reference obj is pointing derived class B's instance..
Type of the reference pointing the object is always checked at compile time, whereas, the type of object pointed by that reference is checked at runtime..
So, the decision of which method will be invoked is made at runtime.. Regardless of the whether your base class method is abstract or not, appropriate derived class method is invoked..
This is not C++. In Java, you always know the real class of each instance so, when printDescription() is invoked, the definition of that class is used. Though, you can only use the methods available in the references to the instance (so, if you define a method getMPH() in class RoadBike and you handle an instance of that class with a Bike variable, the compiler will thow an error if you intend to use it).
I think this code:
bike01 = new Bicycle(20, 10, 1);
bike02 = new MountainBike(20, 10, 5, "Dual");
bike03 = new RoadBike(40, 20, 8, 23);
bike01.printDescription();
bike02.printDescription();
bike03.printDescription();
is not the best example of run-time polymorphism because all facts (methods to call) are known even at compile time.
But if you would change it to:
Random r = new Random();
if(r.nextInt(2)%2==0)
{
bike01 = new Bicycle(20, 10, 1)
}
else
{
bike01 = new MountainBike(20, 10, 5, "Dual");
}
// only at run-time the right function to call is known
bike01.printDescription();
...
I have played around with Scala for a while now, and I know that traits can act as the Scala equivalent of both interfaces and abstract classes. How exactly are traits compiled into Java bytecode?
I found some short explanations that stated traits are compiled exactly like Java interfaces when possible, and interfaces with an additional class otherwise. I still don't understand, however, how Scala achieves class linearization, a feature not available in Java.
Is there a good source explaining how traits compile to Java bytecode?
I'm not an expert, but here is my understanding:
Traits are compiled into an interface and corresponding class.
trait Foo {
def bar = { println("bar!") }
}
becomes the equivalent of...
public interface Foo {
public void bar();
}
public class Foo$class {
public static void bar(Foo self) { println("bar!"); }
}
Which leaves the question: How does the static bar method in Foo$class get called? This magic is done by the compiler in the class that the Foo trait is mixed into.
class Baz extends Foo
becomes something like...
public class Baz implements Foo {
public void bar() { Foo$class.bar(this); }
}
Class linearization just implements the appropriate version of the method (calling the static method in the Xxxx$class class) according to the linearization rules defined in the language specification.
For the sake of discussion, let's look the following Scala example using multiple traits with both abstract and concrete methods:
trait A {
def foo(i: Int) = ???
def abstractBar(i: Int): Int
}
trait B {
def baz(i: Int) = ???
}
class C extends A with B {
override def abstractBar(i: Int) = ???
}
At the moment (i.e. as of Scala 2.11), a single trait is encoded as:
an interface containing abstract declarations for all the trait's methods (both abstract and concrete)
an abstract static class containing static methods for all the trait's concrete methods, taking an extra parameter $this (in older versions of Scala, this class wasn't abstract, but it doesn't make sense to instantiate it)
at every point in the inheritance hierarchy where the trait is mixed in, synthetic forwarder methods for all the concrete methods in the trait that forward to the static methods of the static class
The primary advantage of this encoding is that a trait without concrete members (which is isomorphic to an interface) actually is compiled to an interface.
interface A {
int foo(int i);
int abstractBar(int i);
}
abstract class A$class {
static void $init$(A $this) {}
static int foo(A $this, int i) { return ???; }
}
interface B {
int baz(int i);
}
abstract class B$class {
static void $init$(B $this) {}
static int baz(B $this, int i) { return ???; }
}
class C implements A, B {
public C() {
A$class.$init$(this);
B$class.$init$(this);
}
#Override public int baz(int i) { return B$class.baz(this, i); }
#Override public int foo(int i) { return A$class.foo(this, i); }
#Override public int abstractBar(int i) { return ???; }
}
However, Scala 2.12 requires Java 8, and thus is able to use default methods and static methods in interfaces, and the result looks more like this:
interface A {
static void $init$(A $this) {}
static int foo$(A $this, int i) { return ???; }
default int foo(int i) { return A.foo$(this, i); };
int abstractBar(int i);
}
interface B {
static void $init$(B $this) {}
static int baz$(B $this, int i) { return ???; }
default int baz(int i) { return B.baz$(this, i); }
}
class C implements A, B {
public C() {
A.$init$(this);
B.$init$(this);
}
#Override public int abstractBar(int i) { return ???; }
}
As you can see, the old design with the static methods and forwarders has been retained, they are just folded into the interface. The trait's concrete methods have now been moved into the interface itself as static methods, the forwarder methods aren't synthesized in every class but defined once as default methods, and the static $init$ method (which represents the code in the trait body) has been moved into the interface as well, making the companion static class unnecessary.
It could probably be simplified like this:
interface A {
static void $init$(A $this) {}
default int foo(int i) { return ???; };
int abstractBar(int i);
}
interface B {
static void $init$(B $this) {}
default int baz(int i) { return ???; }
}
class C implements A, B {
public C() {
A.$init$(this);
B.$init$(this);
}
#Override public int abstractBar(int i) { return ???; }
}
I'm not sure why this wasn't done. At first glance, the current encoding might give us a bit of forwards-compatibility: you can use traits compiled with a new compiler with classes compiled by an old compiler, those old classes will simply override the default forwarder methods they inherit from the interface with identical ones. Except, the forwarder methods will try to call the static methods on A$class and B$class which no longer exist, so that hypothetic forwards-compatibility doesn't actually work.
A very good explanation of this is in:
The busy Java developer's guide to Scala: Of traits and behaviors - Traits in the JVM
Quote:
In this case, it [the compiler] drops the method implementations and field declarations defined in the trait into the class that implements the trait
In the context of Scala 12 and Java 8, you can see another explanation in commit 8020cd6:
Better inliner support for 2.12 trait encoding
Some changes to the trait encoding came late in the 2.12 cycle, and the
inliner was not adapted to support it in the best possible way.
In 2.12.0 concrete trait methods are encoded as
interface T {
default int m() { return 1 }
static int m$(T $this) { <invokespecial $this.m()> }
}
class C implements T {
public int m() { return T.m$(this) }
}
If a trait method is selected for inlining, the 2.12.0 inliner would
copy its body into the static super accessor T.m$, and from there into
the mixin forwarder C.m.
This commit special-cases the inliner:
We don't inline into static super accessors and mixin forwarders.
Instead, when inlining an invocation of a mixin forwarder, the inliner also follows through the two forwarders and inlines the trait method body.
I am working with a Java API which requires me to implement a number of fairly large interfaces. However generally there is only one or two details that actually vary between implementations, so I made some abstract base classes to provide most of the implementation.
However now Ive come across cases where I need to extend from some other class and/or implement multiple such interfaces, and so I am unable to extend my abstract base classes.
In C++ I was able to use multiple inheritance, and also use some other tricks like below. However Java doesn't allow multiple inheritance, or generics to be used in this way.
class MyClass : public HelperForInterfaceA, public HelperForInterfaceB {...};
class template<class BASE> MyHelper : public BASE {...};
The best idea I have right now is to have the concrete implementation of my abstract helper class as a field, and then make all the interface methods forward to that field instance, with the field having a reference to the main object to implement the last details if needed.
class MyClass extends A implements IB, IC {
private static class B extends BAbstractHelper {
private A a;
public B(A a, int size) {
super(size);
this.a = a;
}
#Override
public boolean foo(int x, int y) {
return a.foo(x, y);
}
}
private static class C extends CAbstractHelper {
...
}
private B b;
private C c;
private int range;
#Override
public boolean foo(int x, int y) {
return x*x + y*y <= range*range;
}
#Override
public float bar(float x, int y, String s) {
return b.bar(x,y,s);
}
...
}
However this seems a bit of a pain, with a lot of wrapper methods required. Is there a better way of dealing with this?
A Java best practice is to prefer composition over inheritance. Keeps things simpler but creates more boilerplate code. You have the right idea to create delegate methods. A good Java IDE can generate all the boilerplate delegate methods code for you. Other languages on the JVM like Scala (with traits) make this easier.