1
\$\begingroup\$

I'm using Telegram API and I've different methods which returns different type of information like this:

public SendMessage getTextMessage(Long chatId, String text) {
        return new SendMessage()
                .enableMarkdown(false)
                .setChatId(chatId)
                .setText(text);
    }

public AnswerCallbackQuery getPopUpAnswer(String callbackId, String text) {
        return new AnswerCallbackQuery()
                .setCallbackQueryId(callbackId)
                .setText(text)
                .setShowAlert(true);
    }

public EditMessageText getEditedMessage(Long chatId, Integer messageId, String text){
        return new EditMessageText()
                .setChatId(chatId)
                .setMessageId(messageId)
                .setText(text);
    }

public SendPhoto getPhotoMessage(Long chatId, GooglePlayGame game) {
        return new SendPhoto().setChatId(chatId)
                .setPhoto(game.getPictureURL())
                .setCaption(game.toString());
    }

They have one parent PartialBotApiMethod. In main method I handle and execute (send) them:

PartialBotApiMethod<?> responseToUser = updateReceiver.handleUpdate(update);
try {
     execute(responseToUser); //error
    }
catch (TelegramApiException e){
     e.printStackTrace();
    }

But I can't execute PartialBotApiMethod object, only BotApiMethod and their subs. SendPhoto is not in one hierarchy with others, that's why I can't put SendPhoto result to BotApiMethod type variable. And I can't cast like this:

try {
     execute((BotApiMethod)responseToUser);
    }
catch (TelegramApiException e){
     e.printStackTrace();
    }

Because SendPhoto doesn't extends BotApiMethod and I'll give a ClassCastEx.

So I gonna use instanceof and cast "personally":

PartialBotApiMethod<?> responseToUser = updateReceiver.handleUpdate(update);
        if (responseToUser instanceof SendMessage) {
            try {
                execute((SendMessage)responseToUser);
            } catch (TelegramApiException e) {
                e.printStackTrace();
            }
        }
        else if (responseToUser instanceof SendPhoto) {
            try {
                execute((SendPhoto) responseToUser);
            } catch (TelegramApiException e) {
                e.printStackTrace();
            }
        }
        else if (responseToUser instanceof AnswerCallbackQuery) {
            try {
                execute((AnswerCallbackQuery)responseToUser);
            } catch (TelegramApiException e) {
                e.printStackTrace();
            }
        }
        else if (responseToUser instanceof EditMessageText) {
            try {
                execute((EditMessageText)responseToUser);
            } catch (TelegramApiException e) {
                e.printStackTrace();
            }
        }

Do I've better options or just stay with instanceof?

Can I replace instanceof if I cannot use a common interface (third pary API)?

UPDATE

updateReceiver.handleUpdate()

public PartialBotApiMethod handleUpdate(Update update) {
   if (updateHasTextMessage(update)){
       try {
           return processInputMessage(update.getMessage());
       } catch (NotSupportedChatCommandException e) {
           return replyMessageService.getTextMessage(update.getMessage().getChatId(), "Not available");
       }
   }
   else if (updateHasCallbackQuery(update)) {
       return callbackQueryHandler.handleCallbackQuery(update.getCallbackQuery());
   }
   else {
       return replyMessageService.getTextMessage(update.getMessage().getChatId(),
                    "Can't handle");
        }
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Please show updateReceiver.handleUpdate. Is it an API method or one you wrote? \$\endgroup\$
    – Marv
    Jun 30, 2020 at 22:38
  • \$\begingroup\$ It's my own method. \$\endgroup\$
    – takotsubo
    Jul 1, 2020 at 9:36

1 Answer 1

2
\$\begingroup\$

I'm not sure if there is enough context for me to fully understand the restrictions you are wporking with but I will try anyway... 25 years ago an elder university student half-jokingly taught me that the solution to any problem is always to "add another layer of indirection." In this case, split handleUpdate so that each message type has their own handler object and place the type specific request handling into those classes. Furthermore, separate each type specific response handler into their own class (to maintain single responsibility principle) and inject that dependency to each update handler.

I.e. move type specific handling to the module where the type is still known. The function of the instanceof-block you want to get rid of will now effectively be moved to the if-block in the handleUpdate method and you don't need to repeat it again in the response handling code.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.