2016-09-03 4 views
0

Я хочу научиться программировать в Go, я решил в качестве домашнего животного программ я хотел бы сделать простой диспетчеру различных команд до нескольких CommandHandler (если CommandHandler имеет то же имя, что и команда должны обрабатывать.)Как отправить команды вправо CommandHandler по композиции наследования Голанг?

Моих проблема в том, что когда я хочу иметь CommandHandlerManager, который публикует команды, которые будут отправлять правильному CommandHandler, он говорит мне, что мне нужно иметь конкретную реализацию моего HelloWorldCommand, потому что HelloWorldCommandHandler не реализует интерфейс Command. сообщение

Ошибка при компиляции

E:\Desktop\ManBear\golang\src>go run main.go 
# command-line-arguments 
.\main.go:71: cannot use cmdHandler (type HelloWorldCommandHandler) as type CommandHandler in array or slice literal: 
     HelloWorldCommandHandler does not implement CommandHandler (wrong type for Handle method) 
       have Handle(HelloWorldCommand) 
       want Handle(Command) 

я должен был бы, что кто-то объясняет мне, что я делаю неправильно, я предположил, что это означало, что я должен реализовать метод в одиночку функ к моему HelloWorldCommandHandler для интерфейс, как показано ниже:

func (ch HelloWorldCommandHandler) Handle(cmd Command) { 
    fmt.Println("HelloWorldCommandHandler handled the basic command with name --> " + cmd.GetName()) 
} 

Но это создало больше ошибок, связанных с типом.

Рабочий пример того, что я пытаюсь сделать с объяснением того, как и почему я делаю это неправильно, будет оценен.

спасибо.

Вот мой код:

package main 

import (
    "fmt" 
    "strconv" 
) 


type Command interface { 
    GetName() string 
} 


type CommandHandler interface { 
    Command 
    Handle(cmd Command) 
} 


type HelloWorldCommand struct { 
    Command 
    Name string 
    Age int 
} 

func (cmd HelloWorldCommand) GetName() string { 
    return "HelloWorldCommand" 
} 


type HelloWorldCommandHandler struct { 
    CommandHandler 
} 

func (cmd HelloWorldCommandHandler) GetName() string { 
    return "HelloWorldCommand" 
} 

func (ch HelloWorldCommandHandler) Handle(cmd HelloWorldCommand) { 
    fmt.Println("Hello World! My name is " + cmd.Name + " and I'm " + strconv.Itoa(cmd.Age) + " years old!") 
} 

type CommandHandlerManager struct { 
    CommandHandlers []CommandHandler 
} 

func (chm CommandHandlerManager) Publish(cmd Command) { 

    for _, cmdHandler := range chm.CommandHandlers { 
     if cmd.GetName() == cmdHandler.GetName() { 
      cmdHandler.Handle(cmd) 
     } 
    } 
} 


func main() { 

    fmt.Println("Hey my friend!") 

    cmd := HelloWorldCommand {Name: "ManBear", Age: 357} 
    cmdHandler := HelloWorldCommandHandler {} 

    fmt.Println(cmd.GetName()) 
    fmt.Println(cmdHandler.GetName()) 

    cmdHandler.Handle(cmd) 

    cmdHandlerManager := CommandHandlerManager { 
     CommandHandlers: []CommandHandler { 
      cmdHandler, // <-- the error is here 
     }, 
    }; 
} 

UPDATE:

Для любопытных, вот версия functionning моей любимой программы

Благодаря помощи от Dean Elbaz предлагая использовать утверждение типа, он позволяет обрабатывать команду с помощью правильного CommandHandler и использовать правильный набор значений, который прилагается к каждой команде.

package main 

import (
    "fmt" 
    "strconv" 
    "time" 
) 


type Command interface { 
    GetName() string 
} 


type CommandHandler interface { 
    Command 
    Handle(cmd Command) 
} 

const HelloWorldCommandName string = "HelloWorldCommand" 

type HelloWorldCommand struct { 
    Command 
    Name string 
    Age int 
} 

func (cmd HelloWorldCommand) GetName() string { 
    return HelloWorldCommandName 
} 

// Basic Hello World 
type HelloWorldCommandHandler struct { 
    CommandHandler 
} 

func (cmd HelloWorldCommandHandler) GetName() string { 
    return HelloWorldCommandName 
} 

func (ch HelloWorldCommandHandler) Handle(cmd Command) { 
    fmt.Println("Hello World!\n----------------------------------------\n") 
} 

// Hello World with Name and Age 
type HelloWorldWithNameAndAgeCommandHandler struct { 
    CommandHandler 
} 

func (cmd HelloWorldWithNameAndAgeCommandHandler) GetName() string { 
    return HelloWorldCommandName 
} 

func (ch HelloWorldWithNameAndAgeCommandHandler) Handle(cmd Command) { 
    var helloWorldCommand HelloWorldCommand = cmd.(HelloWorldCommand) 
    fmt.Println("Hello World! My name is " + helloWorldCommand.Name + " and I'm " + strconv.Itoa(helloWorldCommand.Age) + " years old!\n----------------------------------------\n") 
} 


const TodayDateTimeCommandName string = "TodayDateTimeCommand" 

// Today's DateTime Command 
type TodayDateTimeCommand struct { 
    Command 
    TimeZone string 
} 

func (cmd TodayDateTimeCommand) GetName() string { 
    return TodayDateTimeCommandName 
} 


type TodayDateTimeCommandHandler struct { 

} 

func (ch TodayDateTimeCommandHandler) GetName() string { 
    return TodayDateTimeCommandName 
} 

func (ch TodayDateTimeCommandHandler) Handle(cmd Command) { 
    var todayCommand TodayDateTimeCommand = cmd.(TodayDateTimeCommand) 
    location, err := time.LoadLocation(todayCommand.TimeZone) 
    if err != nil { 
     fmt.Errorf("Could not load the Location of the TimeZone. %f", err.Error()) 
     return 
    } 
    current_time := time.Now().In(location) 
    fmt.Println("Today's date and time is " + current_time.String() + " for the time zone: " + todayCommand.TimeZone) 
} 


// The CommandHandler Manager 
type CommandHandlerManager struct { 
    CommandHandlers []CommandHandler 
} 

func (chm CommandHandlerManager) Publish(cmd Command) { 

    for _, cmdHandler := range chm.CommandHandlers { 
     if cmd.GetName() == cmdHandler.GetName() { 
      cmdHandler.Handle(cmd) 
     } 
    } 
} 


func main() { 

    fmt.Println("Hey my friend!\n\n\n") 

    cmdHandlerManager := CommandHandlerManager { 
     CommandHandlers: []CommandHandler { 
      HelloWorldCommandHandler {}, 
      HelloWorldWithNameAndAgeCommandHandler {}, 
      TodayDateTimeCommandHandler {}, 
     }, 
    }; 

    cmd := HelloWorldCommand {Name: "ManBear", Age: 357} 
    cmdHandlerManager.Publish(cmd) 

    fmt.Println("~~~~~~~~ other command published ~~~~~~~~~~~~~~~~~~~~~") 
    cmd2 := TodayDateTimeCommand{ TimeZone: "America/Montreal" } 
    cmdHandlerManager.Publish(cmd2) 
} 

ответ

1

подпись Handle должна быть точно func (ch HelloWorldCommandHandler) Handle(cmd Command) { реализовать интерфейс. Быстрое исправление было бы сделать type assertion в начале вашей Handle функции, чтобы получить HelloWorldCommand от вашего Command)

Но я думаю, что это может быть признаком возможного выпуска проекта: если полиморфизм на Command, возможно, команда должна обрабатывать/запускать себя? возможно, с интерфейсом Run() error?

+0

Благодарим вас за «Утверждение типа», оно, похоже, работает для моей цели. – HexaGridBrain