oop - 如何在没有代码冗余的情况下表示两个真正相似的结构?

标签 oop rust polymorphism traits

我想为我的项目创建一个小型图形模块。我确实需要有向图和无向图。

如果是 C++ 或 Java,我会制作一个抽象类 Graph 实现深度优先搜索、广度优先搜索和 2 个子类 Directed 和 Undirected 用于特定实现或特定方法。

我确实读过这本书的 OOP 部分;但是,我将如何用 trait 表示这种行为?

理想情况下,我可以像这样使用我的模组:

use graph::{UndirectedGraph, DirectedGraph, Graph};


pub fn main() {
    let g1 = Undirectedgraph::new(); // implementing Graph trait
    let g2 = DirectedGraph::new(); // implementing Graph trait
    g1.dfs(); // from Graph
    g2.dfs(); // from Graph
    g1.bfs(); // from Graph
    g2.bfs(); // from Graph

    let _ = g1.has_loop(); // from UndirectedGraph implementation only
    let _ = g2.has_loop() // from DirectedGraph implementation only
}

所以我最终得到了这样的结果;如你所见

属性和 getter 仍然有很多冗余:

#[derive(Debug)]
pub struct Node {
    value: i32,
}

pub trait Graph {
    fn get_vertices(&self) -> &Vec<Node>;

    fn print_nodes(&self) {
        self.get_vertices()
            .iter()
            .for_each(|x| println!("{:#?}", x));
    }

    fn bfs(&self) {
        println!("Common implementation");
    }

    fn dfs(&self) {
        println!("Common implementation");
    }

    fn has_loop(&self) -> bool; // should be implemented
}

pub struct DirectedGraph {
    vertices: Vec<Node>,
}

impl Graph for DirectedGraph {
    fn get_vertices(&self) -> &Vec<Node> {
        &(self.vertices)
    }

    fn has_loop(&self) -> bool {
        //some weird stuff
        // specific to DirectedGraph
        true
    }
}

pub struct UndirectedGraph {
    vertices: Vec<Node>,
}

impl Graph for UndirectedGraph {
    fn get_vertices(&self) -> &Vec<Node> {
        &(self.vertices)
    }

    fn has_loop(&self) -> bool {
        //some weird stuff
        // specific to UndirectedGraph
        true
    }
}

最佳答案

您不能直接从特征访问数据的属性(参见Jimmy Cuadra 回答)。然而,正如 kyle 评论的那样,我们可以使用共享的 getter 和 setter。

类似于下面的代码应该可以工作。

trait Graph {
    fn adjacent_edges(&self, v: &Vertex) -> SomeOutput;

    fn dfs(&self, v: &Vertex) -> SomeOutput {
        let adjacent_edges = self.adjacent_edges(v);
        // ...
    }

    fn bfs(&self, v: &Vertex) -> SomeOutput {
        let adjacent_edges = self.adjacent_edges(v);
        // ...
    }
}


struct UndirectedGraph { ... }

impl Graph for UndirectedGraph {
    fn adjacent_edges(&self, v: &Vertex) -> SomeOutput {
        // ...
    }
}


struct DirectedGraph { ... }

impl Graph for DirectedGraph {
    fn adjacent_edges(&self, v: &Vertex) -> SomeOutput {
        // ...
    }
}

关于oop - 如何在没有代码冗余的情况下表示两个真正相似的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57120668/

相关文章:

c# - 存储库类应该在哪里?

perl - 观察 Perl 类中属性的变化

design-patterns - 单一职责和混合

rust - 生命周期参数和函数指针的问题

c++ - 转换为非基类但具有共同祖先

JavaScript 将数组推送到类原型(prototype)问题

rust - 如何在 Rust 中访问代数矩阵的各个元素?

gcc - 使用 Cargo 构建时找不到 `lcrypto` 或 `lssl`

c++ - 理解 C++ 中的多态性

java - 多态性的好处