Как вернуть разные типы в метод, используя дженерики?

, возможно, также не совсем то, что вы ищете, но может сделать трюк (по крайней мере, на могучем Linux). Для меня это работает так, как я хочу, так как я использую скрипты bash, которые запускаются R shiny, и я хочу, чтобы их можно было прервать. Итак, как насчет размещения вашего R-кода в сценарии и запуска скрипта с помощью системной команды?

В приведенном ниже примере я просто использую простой сценарий манекена bash, который запускает команду sleep, тогда как первый аргумент CL количество сна. Все, что находится ниже 10 секунд, не принимается и ставит статус выхода в 1. Кроме того, я получаю некоторый вывод в файле журнала, который я могу контролировать, и, следовательно, прогресс в реальном времени.

Надеюсь, вы найдете это полезным.

library(shiny)

ui <- fluidPage(

# we need this to send costumized messages
tags$head(tags$script(HTML('Shiny.addCustomMessageHandler("jsCode",function(message) {eval(message.value);});'))),

# Sidebar with a slider input for number of bins 
sidebarLayout(
sidebarPanel(

    textInput("duration", "How long you want to wait?"),hr(),
    p("Are you experienced?"),
    actionButton("processbtn", "Yes"),hr(),
    p("Show me what's going on"),
    actionButton("logbtn", "Show me by clicking here."),hr(),
    p("Tired of being experienced?"),
    actionButton("abortbtn", "Yes")

    ), # close sidebar panel 

  # Show a plot of the generated distribution
  mainPanel(
     textOutput("outText"),hr(),
     verbatimTextOutput("outLog")
  ) # close mainpanel
 ) # close sidebar
) # close fluidpage

#------SERVER------------

# Define server logic required to draw a histogram
server <- function(input, output, session) {

# our reactive values that change on button click by the observe functions below
values <- reactiveValues(process = 0, abort = 0, log = 0)

observeEvent(input$processbtn, {
  values$process = 1
  values$abort = 0
  values$log = 0
})

observeEvent(input$abortbtn, {
  values$process = 0
  values$abort = 1
})

observeEvent(input$logbtn, {
   values$log = 1
})

current_state = function(exitfile) {
# get the pid
pid = as.integer(system2("ps", args = "-ef | grep \"bash ~/dummy_script.sh\" | grep -v grep | awk '{print $2}'", stdout = TRUE))
print(pid)

if (length(pid) > 0)
 return("RUNNING")

if (file.exists(exitfile))
 return("TERMINATED")

return("NOT_STARTED")
} 

start_function = function(exitfile) {
 if(input$duration == "") {
  end_message="The text input field is empty!"
  js_string <- 'alert("SUCCESS");'
  js_string <- sub("SUCCESS",end_message,js_string)
  session$sendCustomMessage(type='jsCode', list(value = js_string)) 
  values$process = 0
  return("NOT_STARTED")

 } else { # all checks are fine. send a message and start processing
    end_message="We start waiting, yeah!!!"
   js_string <- 'alert("SUCCESS");'
   js_string <- sub("SUCCESS",end_message,js_string)
   session$sendCustomMessage(type='jsCode', list(value = js_string))  

 # here we execute the outsourced script and
 # write the exit status to a file, so we can check for that and give an error message
 system(paste("( bash ~/dummy_script.sh", input$duration,"; echo $? >", exitfile, ")"), wait = FALSE)
 return("RUNNING")
 }  
}

on_terminated = function(exitfile) {
  # get the exit state of the script
  status = readLines(exitfile)
  print(status)
  # we want to remove the exit file for the next run
  unlink(exitfile, force = TRUE)

  # message when we finished
  if ( status != 0 ){
    end_message="Duration is too short."
    js_string <- 'alert("SUCCESS");'
    js_string <- sub("SUCCESS",end_message,js_string)
    session$sendCustomMessage(type='jsCode', list(value = js_string))
  }
  else {
    end_message="Success"
    js_string <- 'alert("SUCCESS");'
    js_string <- sub("SUCCESS",end_message,js_string)
    session$sendCustomMessage(type='jsCode', list(value = js_string))
  }
  values$process = 0
}

# our main processing fucntion
output$outText = renderText({
   # trigger processing when action button clicked
   if(values$process) {

    # get the homefolder
     homedir=Sys.getenv("HOME")

     # create the path for an exit file (we'll need to evaluate the end of the script)
     exitfile=file.path(homedir, "dummy_exit")
     print(exitfile)

     state = current_state(exitfile) # Can be NOT_STARTED, RUNNING, COMPLETED
     print(state)
     if (state == "NOT_STARTED")
        state = start_function(exitfile)

     if (state == "RUNNING")
        invalidateLater(2000, session = getDefaultReactiveDomain())

     if (state == "TERMINATED")
        on_terminated(exitfile)



   # Abort processing
   } else
   if(values$abort) {
      pid = as.integer(system2("ps", args = "-ef | grep \"bash ~/dummy_script.sh\" | grep -v grep | awk '{print $2}'", stdout = TRUE))
    print(pid)
    system(paste("kill", pid), wait = FALSE)
   }

 }) # close renderText function 

 output$outLog = renderText({

 if(values$log) {

   homedir=Sys.getenv("HOME")
   logfile=file.path(homedir, "/dummy_log")

 if(file.exists(logfile)){
   invalidateLater(2000)
   paste(readLines(logfile), collapse = "\n")
 }
 else {
   print("Nothing going on here")
 }
}

})


} # close server

# Run the application 
shinyApp(ui = ui, server = server)
1
задан Saber 28 March 2019 в 03:28
поделиться

2 ответа

Вы можете изменить свой метод, как показано ниже, приведя к T.

    public <T extends Root> T gets(int type) {
        switch (type) {
            case 1:
                return (T) new A();
            case 2:
                return (T) new B();
            default:
                throw new RuntimeException();
        }
    }
0
ответ дан LeoN 28 March 2019 в 03:28
поделиться

Метод указывает, что существует T, расширяющий Root, который является типом возврата. Однако, пока метод не используется где-то, вы не знаете, какой это класс. Вы не знаете, будет ли T А, или В, или что-то еще. Каждый раз, когда он используется, это будет ровно один подкласс Root.

Но здесь ваш код предполагает, что это будут и A, и B одновременно. На самом деле, T не может быть ни тем, ни другим. Если T является A, вы не можете вернуть экземпляр B. Если T является B, вы не можете вернуть экземпляр A. Если T не является ни A, ни B, вы не можете вернуть ни экземпляр A, ни B.

Вы должны вернуть экземпляр T.

Вы можете не использовать дженерики, а просто вернуть Root.

0
ответ дан Sean F 28 March 2019 в 03:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: