簡體   English   中英

如何將變量的參數化類型設置為變量所在的類類型?

[英]How do I set a parameterized type of a variable to the type of class the variable is in?

我正在制作一個具有多個“命令功能”的 Discord 機器人

public class MyBotCommandFeature extends MyBotFeature {
    @NotNull public final Set<MyBotCommand> commands;

    public MyBotCommandFeature(@NotNull MyBotCommand @NotNull ... commands) {
        if (commands.length == 0) {
            this.commands = new HashSet<>();
        } else {
            this.commands = stream(commands).collect(Collectors.toSet());
        }
    }

    @Nullable
    @CheckForNull
    @CheckReturnValue
    public Set<MyBotCommand> getExtraCommands(@NotNull Guild guild) {
        return null;
    }
}

每個功能都有幾個命令(MyBotCommand)。 MyBotCommand 有兩種抽象方法用於處理文本命令 (runTextCommand) 和斜線命令 (runSlashCommand)。

因為某些命令會想要引用它們所屬的MyBotFeatureMyBotCommandFeature當前是這些抽象方法的參數之一。 但是,要使用任何特定於功能的功能,命令當前必須將MyBotCommandFeatureExampleCommandFeature

public abstract class MyBotCommand {
    public abstract void runTextCommand(@NotNull MessageReceivedEvent event, @NotNull MyBotCommandFeature feature);
    public abstract void runSlashCommand(@NotNull SlashCommandInteractionEvent event, @NotNull MyBotCommandFeature feature);
}
public final class ExampleFeature extends MyBotCommandFeature {
    public ExampleFeature() {
        super(new MyBotCommand() {
            @Override
            public void runTextCommand(@NotNull MessageReceivedEvent event, @NotNull MyBotCommandFeature feature) {
                final ExampleFeature self = ((ExampleFeature) feature);
                // Use self to respond to the text command
            }

            @Override
            public void runSlashCommand(@NotNull SlashCommandInteractionEvent event, @NotNull MyBotCommandFeature feature) {
                final ExampleFeature self = ((ExampleFeature) feature);
                // Use self to respond to the slash command
            }
        });
    }

我希望我能夠使用泛型類型<F extends MyBotCommandFeature>MyBotCommand進行參數化。 然后,它們不是將MyBotCommandFeature作為參數的抽象函數,而是采用F

public abstract class MyBotCommand<F extends MyBotCommandFeature> {
    public abstract void runTextCommand(@NotNull MessageReceivedEvent event, @NotNull F feature);
    public abstract void runSlashCommand(@NotNull SlashCommandInteractionEvent event, @NotNull F feature);
}

但是,我不確定我是否會聲明命令集的類型(在MyBotCommandFeature中定義,而不是在每個功能中單獨定義)來說明通用類型 F 與存儲命令集的類相同.我希望能夠做這樣的事情。

public class MyBotCommandFeature extends MyBotFeature {
    @NotNull public final Set<MyBotCommand<this>> commands;

    public MyBotCommandFeature(@NotNull MyBotCommand<this> @NotNull ... commands) {
        if (commands.length == 0) {
            this.commands = new HashSet<>();
        } else {
            this.commands = stream(commands).collect(Collectors.toSet());
        }
    }

    @Nullable
    @CheckForNull
    @CheckReturnValue
    public Set<MyBotCommand<this>> getExtraCommands(@NotNull Guild guild) {
        return null;
    }
}
public final class ExampleFeature extends MyBotCommandFeature {
    public ExampleFeature() {
        super(new MyBotCommand<ExampleFeature>() {
            @Override
            public void runTextCommand(@NotNull MessageReceivedEvent event, @NotNull ExampleFeature feature) {
                // Use feature to respond to the text command
            }

            @Override
            public void runSlashCommand(@NotNull SlashCommandInteractionEvent event, @NotNull ExampleFeature feature) {
                // Use feature to respond to the text command
            }
        });
    }

我試過使用通配符'? 而不是“this”,但是在將 JDA 事件與 MyBotCommand 匹配后,我被困在傳遞給抽象方法的內容上。 例如,我有這個用於斜杠命令,但我無法將 MyBotCommandFeature 傳遞給 MyBotCommand::runSlashCommand,即使 MyBotCommand 實例是在我傳遞的 MyBotCommandFeature 中創建的。

    @Override
    public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
        for (MyBotCommandFeature feature : features) {
            for (MyBotCommand<?> command : feature.commands) {
                if (command.name.equals(event.getName())) {
                    command.runSlashCommand(event,feature);
                    return;
                }
            }
        }
    }

有什么辦法可以做這樣的事情嗎? 如果沒有,是否有另一種方法可以避免在我的大多數MyBotCommand實現MyBotCommandFeature轉換為單個功能?

這樣的事情怎么樣? MyBotCommand MyBotCommandFeature類型參數。 然后子類ExampleFeature可以擴展MyBotCommandFeature並將其自身作為類型參數。 當然,有人可以編寫一個類FeatureA extends MyBotCommandFeature<FeatureB> ,但一切仍然是類型安全的,並且應該在沒有任何警告或強制轉換的情況下編譯,至少與您目前所展示的一樣。

public abstract class MyBotCommand<F> {
    public abstract void runTextCommand(@NotNull MessageReceivedEvent event, @NotNull F feature);
    public abstract void runSlashCommand(@NotNull SlashCommandInteractionEvent event, @NotNull F feature);
}

public class MyBotCommandFeature<F> extends MyBotFeature {
    @NotNull public final Set<MyBotCommand<F>> commands;

    public MyBotCommandFeature(@NotNull MyBotCommand<F> @NotNull ... commands) {
        if (commands.length == 0) {
            this.commands = new HashSet<>();
        } else {
            this.commands = stream(commands).collect(Collectors.toSet());
        }
    }

    @Nullable
    @CheckForNull
    @CheckReturnValue
    public Set<MyBotCommand<F>> getExtraCommands(@NotNull Guild guild) {
        return null;
    }
}

public final class ExampleFeature extends MyBotCommandFeature<ExampleFeature> {
    public ExampleFeature() {
        super(new MyBotCommand<ExampleFeature>() {
            // ...
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM