Chapel: Chapel Inheritace question

Created on 15 Feb 2018  Â·  8Comments  Â·  Source: chapel-lang/chapel

I would like to store Children instance in Base type variable:

class Base{

proc print(){
    writeln("I am from Base");
}

}


class Child1:Base{

proc print(){
    writeln("I am from Child 1");
}

}



class Child2:Base{

proc print(){
    writeln("I am from Child 2");
}

}

proc main(){

var b:Base;
var c1 = new Child1();
var c2 = new Child2();
b = c1:Base;
b.print();
b = c2:Base;
b.print();

}

I expected the output:

I am from Child 1
I am from Child 2

But I get:

I am from Base
I am from Base

I would like to do as in C++:

class Base{
public:
Base(){}
void print(){
    std::cout<<"I am from Base"<<endl;
}

};


class Child1: public Base{
public:
Child1(){}
void print(){
   std::cout<<"I am from Child 1";
}

}



class Child2: public Base{

void print(){
    std::cout<<"I am from Child 2";
}

};

int main(){
Base* b;
auto* c1 = new Child1();
auto* c2 = new Child2();
b = c1;
b->print();
b = c2;
b->print();
return 0;
}

Compiler Duplicate Bug user issue

All 8 comments

Is it possible you're mixing up your Chapel and C++ versions? The Chapel version appears to do what you want and the C++ version prints "I am from Base" twice.

Here's Chapel:
Try it online!

Here's C++:
Try it online!

I'm seeing the same thing as David Iten's TIO run on master.

@bradcray and @daviditen, thank you very much. I am really confused. Because with this example it works as expected. But now I have a concrete user case where it does not work.

1)I am creating a logger lib for the Chrest restful server. There is a Base class called Logger. This base class has empty methods of logging (Fatal, Write and so on).
2)The concrete Logger needs to inherit from the Logger class and override the method's definition with implementation (such as output to file, output to terminal etc.)

Here is the code:

//Main module
module Main{
use ChrestLogger;

var Log:Logger;
proc main(){
  Log = new DefaultLogger();
  Log.Println("I am printing from my Default Logger");
  Log = new DefaultLogger2();
  Log.Println("I am printing from my DefaultLogger2");

}

}

The Chrestlogger is:

//Chrest Logger
module ChrestLogger{

    class Logger{
        proc  Fatal(v ...?eltType){

        }
        proc  Fatalf(format:string, v...?eltType){

        }
        proc  Fatalln(v...?eltType){

        }

        proc  Panic(v...?eltType){

        }
        proc  Panicf(format:string, v ...?eltType){

        }
        proc  Panicln(v...?eltType){

        }
        proc  Print(v...?eltType){

        }
        proc  Printf(format:string, v...?eltType){

        }
        proc  Println(v...?eltType){
        }

    }


    class DefaultLogger:Logger{
        proc DefaultLogger(){

        }

        proc  Fatal(v ...?eltType){
            write((...v));
        }
        proc  Fatalf(format:string, v...?eltType){
            writef(format,(...v));
        }
        proc  Fatalln(v...?eltType){
            writeln((...v));
        }

        proc  Panic(v...?eltType){
            writeln((...v));
        }
        proc  Panicf(format:string, v ...?eltType){
            writef(format,(...v));
        }
        proc  Panicln(v...?eltType){
            write((...v));
        }
        proc  Print(v...?eltType){
            write((...v)); 
        }
        proc  Printf(format:string, v...?eltType){
             writef(format,(...v));
        }
        proc  Println(v...?eltType){
             writeln((...v));
        }

        proc  Write(v...?eltType){
            write((...v)); 
        }
        proc  Writef(format:string, v...?eltType){
             writef(format,(...v));
        }
        proc  Writeln(v...?eltType){
             writeln((...v));
        }

    }
    class DefaultLogger2:Logger{
        proc DefaultLogger(){

        }

        proc  Fatal(v ...?eltType){
            write("Logger2: ",(...v));
        }
        proc  Fatalf(format:string, v...?eltType){
            writef("Logger2: ",format,(...v));
        }
        proc  Fatalln(v...?eltType){
            writeln("Logger2: ",(...v));
        }

        proc  Panic(v...?eltType){
            writeln("Logger2: ",(...v));
        }
        proc  Panicf(format:string, v ...?eltType){
            writef("Logger2: ",format,(...v));
        }
        proc  Panicln(v...?eltType){
            write("Logger2: ",(...v));
        }
        proc  Print(v...?eltType){
            write("Logger2: ",(...v)); 
        }
        proc  Printf(format:string, v...?eltType){
             writef("Logger2: ",format,(...v));
        }
        proc  Println(v...?eltType){
             writeln("Logger2: ",(...v));
        }

        proc  Write(v...?eltType){
            write("Logger2: ",(...v)); 
        }
        proc  Writef(format:string, v...?eltType){
             writef("Logger2: ",format,(...v));
        }
        proc  Writeln(v...?eltType){
             writeln("Logger2: ",(...v));
        }

    }

}

I expected to have the output as:

I am printing from my Default Logger
Logger2: I am printing from my DefaultLogger2

But it calls the Base methods that are void.

I need somenthing that works as interface contract such as interface for Java or Abstract class for C++.
With the CDO I could do that with forwading mechanism. But with the same methodology I cannot reproduce the same feature with Logger.

Please, help-me visualize my big problem. I have the probability of 70% that I am missing something. But I want assure that it is not somenthing about the compiler itself.
Please, understand that I am not making criticism on the compiler, but that I am asking help to know how to do this kind of "idiomatism". All projects that I do in chapel needs this kind of inheritance overriding.

Except for this small problem, I am enjoying the language.
Thank you very much!

@marcoscleison - I believe the example you've written should work as expected, but you are hitting a particular bug with overridden methods that take variadic-arguments: https://github.com/chapel-lang/chapel/issues/6928

I need somenthing that works as interface contract such as interface for Java or Abstract class for C++.

We have a proposal to add something sortof like interface in Java to the language in the form of CHIP 2 which has its own issue #6040 which your are welcome to +1 if you feel it's going in the right direction.

In the meantime though, the inheritance pattern you have here is reasonable and should work. But there is a known bug you're running into - issue #6928 - which you ran into once already in #7768.

Thanks @marcoscleison. I see the problem behavior in your new example. I reduced it a bit to make it less to look at:

class Logger {
  proc  Println(v...?eltType) {
    writeln("BaseLogger: ", (...v));
  }
}

class DefaultLogger: Logger {
  proc  Println(v...?eltType) {
    writeln("Logger: ", (...v));
  }
}

class DefaultLogger2: Logger {
  proc  Println(v...?eltType) {
    writeln("Logger2: ", (...v));
  }
}

var Log: Logger;
Log = new DefaultLogger();
Log.Println("I am printing from my Default Logger");
Log = new DefaultLogger2();
Log.Println("I am printing from my DefaultLogger2");

Thanks, everybody. In fact, I realized that the problem is really the overriding variadic methods. It is making things difficult to abstract. If possible, add this in to do list. I really appreciate.

This issue should now be fixed in master as of https://github.com/chapel-lang/chapel/pull/9018. Thanks for reporting it!

Was this page helpful?
0 / 5 - 0 ratings