Generic Object Creation

I want to implement a generic method to create instance of ItemComponents from Items. Here is my design.

Item Implementation

class UItemBase : public UObject
{
    UPROPERTY(...) TSubclassOf<UItemComponentBase> ComponentClass;
}
class UItemClassA: public UItemBase;
class UUtemClassB: public UItemBase;

Component Implementation

class UItemComponentBase: public UActorComponent
{
    UPROPERTY(...) UItem* ItemInstance;
}
class UItemComponentA: public UItemComponentBase;
class UItemComponentB: public UItemComponentBase;

Now, I want to instantiate specific component for specific item.

bool ASomeActor::AddItemComponent(TSubclassOf<UItemBase> ItemClass)
{
    UItemBase* ItemTemplate = ItemClass.GetDefaultObject();
    UItemComponentBase* ItemComponent = NewObject<UItemComponentBase>(this, ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate ->ComponentClass.GetDefaultObject());
    ItemComponent ->ItemInstance = NewObject<UItemBase>(ItemComponent , ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate);
    ItemComponent ->RegisterComponent();
    return true;
}

Of course, the code is not instantiating the child classes, they are just instances of UItemComponentBase. How can I achieve this? Is it possible to implement a generic method for that or do I need to check the type and write different code for each class type?

Edit:
I can only achieve this by type checking and writing different methods for each UItemComponent subclass.

bool ASomeActor::AddItemComponent(TSubclassOf<UItemBase> ItemClass)
{
    UItemBase* ItemTemplate = ItemClass.GetDefaultObject();
    if (ItemTemplate ->IsA<UItemClassA>())
    {
        UItemComponentA* ItemComponent = NewObject<UItemComponentA>(this, ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate ->ComponentClass.GetDefaultObject());
        ItemComponent ->ItemInstance = NewObject<UItemClassA>(ItemComponent , ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate);
        ItemComponent ->RegisterComponent();
    }
    else if (ItemTemplate ->IsA<UItemClassB>())
    {
        UItemComponentB* ItemComponent = NewObject<UItemComponentB>(this, ItemComponentTemplate ->Name, EObjectFlags::RF_NoFlags, ItemComponentTemplate ->ComponentClass.GetDefaultObject());
        ItemComponent ->ItemInstance = NewObject<UItemClassB>(ItemComponent , ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate);
        ItemComponent ->RegisterComponent();
    }
    //... so on
}

checking for the type of class in a switch case, is a sign that your breaking encapsulation and not properly delegating tasks. your design makes ASomeActor a high-maintenance, all-knowing class, that needs new code for every new item subclass you create.

instead, you should put a virtual function in the item base class that returns its corresponding component. then, when you add a new item subclass, you just need to set the ItemComponentClass variable in the default properties.

each item should be responsible for knowing its own related parts. external objects that communicate with items, should not know anything about specific items or their related parts, they should just know how to communicate with the interface of the base item.

So I done this with the virtual functions. Any other / better approach will be welcomed. Thanks Omnicypher.

class UItemBase : public UObject
{
    virtual UItemComponentBase* CreateComponent(AActor* Owner) { return nullptr; }
}
class UItemClassA: public UItemBase
{
    virtual UItemComponentBase* CreateComponent(AActor* Owner) override;
}

UItemComponentBase* UItemClassA::CreateComponent(AActor* Owner)
{
    UItemComponentA* ItemComponent = NewObject<UItemComponentA>(Owner, "Name");
    // ...
    return ItemComponent;
}

And just called the “CreateComponent” method for any “Item”.