Expose properties of another class to the editor

I have a door derived from AActor that can be locked. It contains several locking-related variables and functions, eg. bool isLocked, uint32 keyID, etc. Since doors aren’t the only thing in my game that can be locked, I decided to move those lock-related things into their own class, called Lockable. The declaration of the door class is now like this:

UCLASS()
class ADoor : public AActor, public Lockable { ...

I want to be able to set isLocked and keyID in the properties panel of the editor when I drag a door actor onto the stage. Using the UPROPERTY() macro in the Lockable class does nothing. How can I accomplish this?

Also wondering if this would be possible for actors containing other actors, say I have an ALock* object inside the door class and would like to set some variables of it.

I would also like to surface UPROPERTYs from other classes used as data members. However, I don’t think it’s possible. The only workaround I can think of is to copy the UPROPERTYs you want into the root class and forward changes to the object. For example in the header of my actor component I have:

UTestType* Test; // some object I delegate work to

UPROPERTY(EditAnywhere)
float Foo; // where Foo is actually a property on UTestType

and after the value is changed in editor, forward the message:

void UDistributeComponent::PostEditChangeProperty(struct FPropertyChangedEvent& e)
{
	const FName PropertyName = e.Property->GetFName();
	if (PropertyName == GET_MEMBER_NAME_CHECKED(UDistributeComponent, Foo))
	{
		Test->Foo = Foo; // forward message
	}

You could have the Lockable class derive from AActor, and then have any lockable actors derive from it:

    UCLASS()
    class ALockable : public AActor {

        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Locking")
        bool isLocked;

        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Locking")
        int32 keyID;

        ...


UCLASS()
class ADoor : public ALockable {...

UCLASS()
class ANotherLockableActor : public ALockable {...

This gets a little unwieldy if you have lots of combinations.
The other way to go about is by placing your Lockable functionality within a component.

//within LockableComponent.h
UCLASS()
class ULockableComponent : public UActorComponent {...


//within Door.h
UCLASS()
class ADoor : public AActor {
    //constructor
    ADoor::ADoor();

    ...

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
    ULockableComponent* LockableComponent;

    ...


//within Door.cpp
ADoor::ADoor ()
    :
    AActor
{

    ...

    LockableComponent = CreateDefaultSubobject<ULockableComponent>(TEXT("LockableComponentName"));

    ...

}

You can also use CreateOptionalDefaultSubobject in your constructor; or you can create the object dynamically after spawn in a separate method via NewObject.

In the editor your isLockable and keyID properties would appear as values within the LockableComponent property.