2015-01-15 3 views
1

Я иду из C++, и я пытаюсь наследовать тип параметра Generic в Java. В принципе, я пытаюсь подражать ниже C++ шаблон:Java extend Generic Type Parameter

В C++, я могу сделать:

#include <iostream> 

class Node 
{ 
     Node* next; 
}; 


class BaseVisitor 
{ 
    public: 
     BaseVisitor(Node* ptr) 
     { 
      std::cout<<ptr<<"\n\n"; 
      delete ptr; 
     } 
     ~BaseVisitor() {}; 

    protected: 
     virtual Node* Generate() = 0; 
}; 


class DynamicVisitor : public BaseVisitor 
{ 
    public: 
     DynamicVisitor(Node* ptr) : BaseVisitor(ptr) {} 

    protected: 
     virtual Node* Generate() 
     { 
      std::cout<<"Dynamic Visitor\n"; 
      return new Node(); 
     } 
}; 

class StaticVisitor : public BaseVisitor 
{ 
    public: 
     StaticVisitor(Node* ptr) : BaseVisitor(ptr) {} 

    protected: 
     virtual Node* Generate() 
     { 
      std::cout<<"Static Visitor\n"; 
      return NULL; 
     } 
}; 



template<typename T> 
class TestVisitor : public T //THIS is where the magic happens.. 
{ 
    public: 
     TestVisitor() : T(this->Generate()) {} //allows me to call "Generate". 
}; 

int main() 
{ 
    TestVisitor<DynamicVisitor> foo = TestVisitor<DynamicVisitor>(); 
    TestVisitor<StaticVisitor> bar = TestVisitor<StaticVisitor>(); 
} 

Выход:

Dynamic Visitor 
0x605ed0 

Static Visitor 
NULL 

Как я могу сделать то же самое в Java? Я пробовал:

public class Node { 
    Node next; 
} 

public abstract class BaseVisitor { 
    public BaseVisitor(Node n) {System.out.println(n);} 

    protected abstract Node generate(); 
} 

public class DynamicVisitor extends BaseVisitor { 
    public DynamicVisitor(Node n) { 
     super(n); 
    } 

    @Override 
    protected Node generate() { 
     return new Node(); 
    } 
} 

public class StaticVisitor extends BaseVisitor { 

    public StaticVisitor(Node n) { 
     super(n); 
    } 

    @Override 
    protected Node generate() { 
     return null; 
    } 
} 

public class TestVisitor<T extends BaseVisitor> extends T { //error.. Cannot extend "T".. No magic happens.. 
    public TestVisitor() { 
     super(this.generate()); //cannot call generate().. 
    } 
} 
  1. Что эта модель называется? Я называю это шаблоном «Base Factory», но я не уверен, что это настоящее имя, поэтому я не был уверен, что искать.

  2. Как я могу сделать то же самое, что и на C++, на Java? Есть ли какой-либо способ сделать один и тот же шаблон в Java?

+0

Это где C++ zings в то время как java zangs. В C++ шаблоны - это в основном причудливые макросы препроцессора, которые приводят к созданию разных создаваемых объектов времени исполнения. В java существует только одна версия шаблонизированного класса во время выполнения (с стираемым типом параметра). Это запрещает вам делать такие вещи, как выше. Однако вы можете придумать решения, используя анонимные классы или java 8 lambdas. –

ответ

1

Нет, не могу сделать это в java, извините. Ближайший это, наверное, «делегат шаблон»:

public interface NodeGenerator { Node generate(); } 
public class StaticGenerator implements NodeGenerator { 
    public Node generate() { return null; } 
} 
public class DynamicGenerator implements NodeGenerator { 
    public Node generate() { return new Node(); } 
} 

public class TestVisitor extends BaseVisitor { 
    public TestVisitor(NodeGenerator g) { super(g.generate()); } 
} 

В Java 8, вы можете сделать это выглядеть лучше (но, возможно, менее эффективно), без дополнительных интерфейсов и классов:

public class TestVisitor extends BaseVisitor { 
    public TestVisitor(Supplier<Node> g) { super(g.get()); } 
} 

// ... and then you can do things like 

TestVisitor staticVisitor = new TestVisitor(() -> null); 
TestVisitor dynamicVisitor = new TestVisitor(() -> new Node()); 
+0

Почему вы предполагаете, что это возможно менее эффективно? –

+0

Ну, я сказал «возможно», потому что я не уверен, как именно это реализовано. Что я имею в виду, это примерно так: 'NodeGenerator ng = new StaticNodeGenerator(); for (int i = 0; i <10000; i ++) {new TestVisitor (ng); } 'vs.' for (int i = 0; i <10000; i ++) {new TestVisitor (() -> null); } '. Мне кажется, что последний подход будет выделять еще 10000 объектов (чего можно избежать) и, возможно, *, генерировать 10000 дополнительных анонимных классов (что было бы неизбежно). – Dima

+0

Вы можете заменить первый пример анонимными классами и получить код, который почти такой же краткий, как и версия java 8! –