Как реализовать несколько черт для одного типа и выбрать между чертами? - PullRequest
0 голосов
/ 30 мая 2019

Как бы вы обычно обрабатывали что-то подобное в Rust?

class Base(Model):
    def do_something(self, x):
        return {"base": x * 2}

class A(Model):
    extend = Base
    def do_something(self, x):
        res = super(A, self).do_something()
        res['test'] = x
        return res

class B(Model):
    extend = Base
    def do_something(self, x):
        if x > 5:
            res = super(B, self).do_something()
        else:
            res = {}
        return res

obj = Base()
obj.do_something(1)
>> {}
obj.do_something(6)
>> {'test': 6, 'base': 12}

В Python у меня было бы нечто подобное, когда класс Base непрерывно расширяется с помощью метакласса.Вы всегда используете класс Base, а остальные являются просто синтаксическим сахаром для расширения класса Base.

Как вы можете видеть, в теле B.do_something порядок, в котором вызываются методыуправляется телом функции, а не последовательно, поэтому невозможно просто сохранить список функций и затем вызвать их последовательно.

В Python большая часть логики скрыта за метаклассом, но идея состоит в том, чтобы предложить разработчикам расширений единственное место, добавляющее методы в модель, чтобы не знать, как какой-то другой модуль также присоединяется кта же модель.

Например, Base ведет себя немного как прокси.Всякий раз, когда другой класс наследует его, он создает новый тип, основанный на верхнем типе.Когда вы вызываете метод, он делает что-то вроде return getattr(self._inner, name)(args) и использует обычное наследование в Python для получения super.Когда он расширяет его, все, что он делает, это self.top = type(self.name, (self.top,), args...), но поскольку у Rust нет наследования, я не уверен, как это можно сделать.

Есть ли способ достичь чего-то близкого в Rust?без того, чтобы сделать код полностью нечитаемым?

Как я понимаю, одним из способов достижения этого было бы создание объектов функторов

наподобие

struct Command {
   name: String,
   super: &command: Command,
   func: Fn (&Object, &Command
, ArgumentMap) -> Any
}

struct Object {
   name: String,
   commands: Map<Command>,
}

impl Object {
  fn insert_command(&self, command: Command) {
    let super_command = self.commands.get(command.name)
    if (super_command) {
      command.super = super_command
    }
    self.commands.remove(super_command.name)
    self.commands.set(command.name, command)
  }

  fn call(&self, name:String, args: ArgumentMap) -> Any {
    let command = self.commands.get(command.name)
    (command.func)(self, command.super, args)
  }

  fn extend(extension: Map<String, ?closure?>) {
     // for each key add a command
  }
}

user = Object {
    name: "user",
    commands: Map<Command> {}
}

user.extend({
  "do_something": |self, super, args| {
     // change args
     let new_args = self.call("change_args", args)
     let ret = (super.func)(self, super.super, new_args)
     // do something with ret
  },
})

user.extend({
    "do_something": |self, super, args| {
       // will call method previously defined above
       let ret = (super.func)(self, super.super, args)
       ret
    }
})

Это во многомсделай это.Object - это простой объект, который предназначен для хранения функций по мере необходимости.Это можно сделать лучше, сделав super как вызываемый объект, который принимает args в качестве аргумента только путем инкапсуляции (self, следующий супер метод).

Вот как я это сделаю, когда я неЯ не знаю, можно ли сделать подобные вещи без реализации объектоподобной структуры.Все это будет выполняться во время выполнения, но я полагаю, что иначе сделать невозможно, потому что существует необходимость в размышлении, если предполагается, что что-то вызывается извне с использованием запроса JSON.Давайте представим, что одной из точек входа является веб-сервер, который получает метод, вызываемый в модели.Как я понимаю, Rust не предлагает отражения, поэтому имеет смысл делать это так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...