сегодня я узнал, что ржавчина не поддерживает ковариантность для параметра fn, только его возвращаемый тип является ковариантным. (см. документацию по rust)
Почему я узнал об этом факте в ржавчине? Потому что я попытался реализовать очень простую игру, в которой я разделил логику, обработку событий и рисование на три отдельные функции, но все они работают с одним и тем же вектором игроков.
Если это невозможно, что будет эквивалентно в Rust по сравнению с версией C#?
В C# это довольно просто Fiddle. Вы можете определить интерфейс Y, который должен реализовать класс X, и определить соответствующий делегат, который требует в качестве параметра IEnumerable этого интерфейса Y. Теперь вы можете совместно использовать список X между различными методами, которым требуется только интерфейс Y.
using System;
using System.Collections.Generic;
public interface Actionable{
void Do();
}
public interface Drawable{
void Draw();
}
public class Player: Drawable, Actionable{
public void Do(){
Console.WriteLine("Action");
}
public void Draw(){
Console.WriteLine("Draw");
}
}
public class Program
{
public delegate void DrawHandler(IEnumerable<Drawable> obj);
public delegate void LogicHandler(IEnumerable<Actionable> obj);
public static void gameloop(DrawHandler draw,LogicHandler action){
List<Player> list = new List<Player>(){
new Player()
};
for(int rounds = 0; rounds < 500; rounds++){
draw(list);
action(list);
}
}
public static void Main()
{
gameloop(
list =>{
foreach(var item in list){
item.Draw();
}
},
list =>{
foreach(var item in list){
item.Do();
}
}
);
}
}
Как бы я ни был наивен, я пытался сделать что-то похожее на ржавчину!
trait Drawable {
fn draw(&self) {
println!("draw object");
}
}
trait Actionable {
fn do_action(&self, action: &String) {
println!("Do {}", action);
}
}
#[derive(Debug)]
struct Position {
x: u32,
y: u32,
}
impl Position {
fn new(x: u32, y: u32) -> Position {
Position { x, y }
}
}
#[derive(Debug)]
struct Player {
pos: Position,
name: String,
}
impl Player {
fn new(name: String) -> Player {
Player {
name,
pos: Position::new(0, 0),
}
}
}
impl Drawable for Player {
fn draw(&self) {
println!("{:?}", self);
}
}
impl Actionable for Player {
fn do_action(&self, action: &String) {
println!("Do {} {}!", action, self.name);
}
}
type DrawHandler = fn(drawables: &Vec<&dyn Drawable>) -> Result<(), String>;
type LogicHandler = fn(actions: &Vec<&dyn Actionable>) -> Result<(), String>;
type EventHandler = fn(events: &mut sdl2::EventPump) -> Result<bool, String>;
fn game_loop(
window: &mut windowContext,
draw_handler: DrawHandler,
event_handler: EventHandler,
logic_handler: LogicHandler,
) -> Result<(), String> {
let mut objects: Vec<&Player> = Vec::new();
objects.push(&Player::new("b".to_string()));
while event_handler(&mut window.events)? {
logic_handler(&objects)?; // Does Not work
window.canvas.clear();
draw_handler(&objects)?; // Does Not Work
window.canvas.present();
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
}
Ok(())
}
Если это невозможно, что будет эквивалентно в Rust по сравнению с версией C#?
Я согласен, что это невозможно в ржавчине. Я хотел бы знать, что вместо этого используется в ржавчине