2

In Delphi there are the so called class references:

type
  TSomeClass = class(TAncestorClass)
  .
  .
end;
// They are declared with some weird syntax: (I know Java has no type declarations)
type   
 TSomeClassReference = class Of TSomeClass;  

Stated such declaration, it can be used as an argument

// you can pass TSomeClassReference or any descendant class this function
function ClassFactory (pClassToCreate : TSomeClassReference) : TSomeClass;

// invoke with  
var
A : TSomeClass;  
B : TSomeClassDerivedFromTSomeClass;  

A := ClassFactory (TSomeClass);
B := ClassFactory (TSomeClassDerivedFromTSomeClass);
B := ClassFactory (TAnotherClass); // wrong!

or instance variable

TAnotherClass = class(TAnyClassNotDerivedFromTSomeClass)
  .
  .
  // same: can hold reference to TSomeClass or any descendant
  FDriverClass : TSomeClassReference;
end;  

var  
  A : TAnotherClass;  

  A.FDriverClass := TSomeClass;  
  A.FDriverClass := TSomeClassDerivedFromTSomeClass;  
  A.FDriverClass := TAnotherClass;   // wrong!  

I heavyly use such class references in Delphi for creating class factories among other things. Is there a syntax in Java for doing this? I mean something like

public TSomeClass ClassFactory (pClassToCreate TSomeClassReference) 
{...}

or

public class TAnotherClass extends TAnyClass { 
   TSomeClassReference FDriverClass;
}
5
  • I tried to edit your question to properly format the code, but I gave up because it's all over the place. Please use the appropriate code block for encapsulating code in a question. Commented Jul 17, 2015 at 16:35
  • Java does not support metaclasses in the same way Delphi does. I believe you can do something similarish with java.lang.Class<T> though Commented Jul 17, 2015 at 16:40
  • Code blocks are formated using Ctrl+K, only use backticks for code snippet inside an otherwise normal sentence. And greetings and regards are considered fluff on SO and discouraged. Commented Jul 17, 2015 at 16:57
  • For those who are not familiar with Delphi, they are similar to Smalltalk's metaclasses. (Delphi has a number of interesting language features like that.) So far as I know, Java doesn't support Delphi-style metaclasses, and that's one reason for the common factory patterns you see in Java code. Maybe you can state what you're trying to achieve, and someone can answer with the canonical Java-style way to do it? Commented Jul 17, 2015 at 17:19
  • I want to create an object from a class reference (One more field is required to more clearly state this) like Delphi does: TAnotherClass = class(TAnyClassNotDerivedFromTSomeClass) . . FDriverClass : TSomeClassReference; FDriver : TSomeClass; end; var A : TAnotherClass; A.FDriverClass := TSomeClassDerivedFromTSomeClass; // TSomeClassDerivedFromTSomeClass.Create A.Driver := A.FDriverClass.Create; A.FDriverClass := TAnotherClassDerivedFromTSomeClass; // TAnotherClassDerivedFromTSomeClass.Create A.Driver := A.FDriverClass.Create; Commented Jul 22, 2015 at 1:49

2 Answers 2

5

In Java 7 you can get a class reference by add the .class to the class name.

e.g.

Class<Integer> iClass = Integer.class

However, if you want to use a factory, it is recommended in Java 8 you use a Supplier as this is far more flexible.

Supplier<Integer> iSupplier = () -> new Integer(0);
Integer i = iSupplier.get();
Sign up to request clarification or add additional context in comments.

4 Comments

This is not exactly the answer to the question. Namely, Class<Integer> can only hold Integer.class and not its sub classes. In Delphi meta class variable can also hold any subclass of class used in meta class declaration.
@DalijaPrasnikar so you mean Class<? extends MyClass> instead? The question is about factory methods, how does delphi know which class to create if it could be any sub-class, and not refering to a specific class?
Exactly. Delphi metaclass - TMyClassReference = class of TMyClass declares type and variable of that type stores actual class.
I have updated my answer with simple Delphi object factory code to illustrate how Delphi meta class can be used.
1

In Java Class is equivalent of TClass in Delphi. Java Object class has getClass() method that returns class of particular object instance, similar to Delphi's TObject class ClassType method

public final Class<?> getClass() // Java

function ClassType: TClass; // Delphi

For example type of String.class is Class<String>

To get equivalent of Delphi metaclass TSomeClassReference declared as

  TSomeClassReference = class Of TSomeClass;

in Java you would use upper bounded wildcard on Class<T>

  Class<? extends SomeClass>

That will give you same compile time type checking like Delphi has.


Following example demonstrates simple object factory in Java

public class BaseClass
{
    public int b = 0;

    public BaseClass()
    {
        b = 10;
    }
}

public class ClassA extends BaseClass
{
    public ClassA()
    {
        b = 20;
    }
}

public class ClassAA extends ClassA
{
    public ClassAA()
    {
        b = 22;
    }
}

public class ClassB extends BaseClass
{
    public ClassB()
    {
        b = 30;
    }
}

public class BaseFactory 
{
    public static BaseClass create(Class<? extends BaseClass> clazz)
    {
        try
        {
            return clazz.getConstructor().newInstance();
        }
        catch (NoSuchMethodException e)
        {
            e.printStackTrace();
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
        return null;
    }
}

And then you can use your factory to create objects like

Class<? extends BaseClass> c = ClassA.class;
BaseClass o = BaseFactory.create(c);

or

BaseClass o = BaseFactory.create(BaseClass.class);
BaseClass o = BaseFactory.create(ClassA.class);
BaseClass o = BaseFactory.create(ClassAA.class);
BaseClass o = BaseFactory.create(ClassB.class);

Class<? extends BaseClass> c = String.class; // this will not compile
BaseClass o = BaseFactory.create(String.class); // this will not compile

Equivalent object factory in Delphi - type names have been changed to match Delphi coding style.

BaseClass - TBaseObject

ClassA - TObjectA

Class<? extends BaseClass> - TBaseClass

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes;

type
  TBaseObject = class(TObject)
  public
    b: integer;
    constructor Create; virtual;
  end;

  TBaseClass = class of TBaseObject;

  TObjectA = class(TBaseObject)
  public
    constructor Create; override;
  end;

constructor TBaseObject.Create;
begin
  inherited;
  b := 10;
end;

constructor TObjectA.Create;
begin
  inherited;
  b := 20;
end;

function BaseFactory(clazz: TBaseClass): TBaseObject;
begin
  Result := clazz.Create;
end;

var
  o: TBaseObject;
  c: TBaseClass;
begin
  o := BaseFactory(TBaseObject);
  writeln(o.b); // 10
  o.Free;

  o := BaseFactory(TObjectA);
  writeln(o.b); // 20
  o.Free;

  c := TObjectA;
  o := BaseFactory(c);
  writeln(o.b); // 20
  o.Free;

  readln;
end.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.