目前,我正在学习 Scala,现在,我对比较对象的有序特征有些困惑。
考虑下面的例子,这是我目前对比较的理解,
Case I,
class Example(var n: Int) extends Ordered[Example] {
// ...
def compare(that: Example) =
(this.n) - (that.n)
}
var obj1 = new Example(12)
var obj2 = new Example(12)
obj1 compare obj2 //return 0 i.e. obj1 and obj2 are equal.
Case II,
class Example(var m: Int, var n: Int) extends Ordered[Example] {
// ...
def compare(that: Example) =
(this.m * this.n) - (that.m * that.n)
}
var obj1 = new Example(1, 2)
var obj2 = new Example(1, …Run Code Online (Sandbox Code Playgroud) 我正在尝试返回具有特征main_func的类型结构的向量TSrObject
struct TestA {
value: u8,
}
pub trait SrObject {
fn myfunc(&mut self);
}
impl SrObject for TestA {
fn myfunc(&mut self) {
unimplemented!();
}
}
impl Default for TestA {
fn default() -> TestA {
TestA { value: 3u8 }
}
}
fn main_func<T: SrObject>(t: T) -> Vec<T> {
let mut v = Vec::<T>::new();
for i in 0..10 {
v.push(T::default());
//v[i].myfunc();
}
return v;
}
Run Code Online (Sandbox Code Playgroud)
它给:
struct TestA {
value: u8,
}
pub trait …Run Code Online (Sandbox Code Playgroud) 我是Scala菜鸟,请看下面的代码。
abstract class Pizza() {
def toppings: List[String]
def price: BigDecimal
}
trait Large extends Pizza {
abstract override def price: BigDecimal = super.price * 2
}
trait Cheese extends Pizza {
abstract override def toppings: List[String] = "Cheese" :: super.toppings
abstract override def price: BigDecimal = super.price + 0.5
}
trait Salami extends Pizza {
abstract override def toppings: List[String] = "Salami" :: super.toppings
abstract override def price: BigDecimal = super.price + 1.0
}
class BasePizza extends Pizza { …Run Code Online (Sandbox Code Playgroud) 我想理解为什么对 Traits 的讨论似乎从来不包括与 Require 的比较,而是总是与继承进行比较。
据我了解,Require 本质上与运行时的复制/粘贴相同,并且 Require_Once 确保代码不重复。特征通常也被称为与复制/粘贴几乎相同。
也就是说,Require 和 Include 可以在条件逻辑中使用,因此在某些情况下它们可以成为 Trait 的更好替代方案。Traits 具有多态性和其他理想的功能,而这些功能是严格复制代码所无法获得的。例如,能够抽象特征中的函数,然后选择性地在容器类中重写。
这两个“代码包含/导入”功能在范围方面具有相似的行为,例如 $this。
但一个明显的区别是 Include/Require 代码默认会进入 HTML 处理,并且 <?php 是可选的,具体取决于上下文,通过 Trait 我们知道代码必须是 PHP 并且必须以 <?php 为前缀。
所以对我来说,Trait 更像是一个更高级别的 OOP 工具,而 Require 是一个不了解 OOP 细节的语言级指令。然而,在许多情况下,使用 Require 代码似乎比使用 Trait 来包含相同的代码同样简单和有用。
我希望有人能够提供清晰的示例,其中将选择一个而不是另一个,以便更明显地应该使用哪一个。除了我所引用的内容之外,还有更多细节。我是否已经走在做出这些选择的正确道路上?比这更简单,还是更复杂?比较表将是理想的。
对于一个类型
pub struct Child<'a> {
buf: &'a mut [u8],
}
Run Code Online (Sandbox Code Playgroud)
我可以定义一个特征并实现该类型的特征,但其生命周期绑定到调用函数的上下文(而不是本地循环上下文):
pub trait MakeMut<'a> {
fn make_mut(buf: &'a mut [u8]) -> Self;
}
impl<'a> MakeMut<'a> for Child<'a> {
fn make_mut(buf: &'a mut [u8]) -> Self {
Self { buf }
}
}
Run Code Online (Sandbox Code Playgroud)
首先展示一个有点有效的示例,因为x仅在循环上下文中借用,因为 Child::make_mut 是在函数中硬编码的map1:
pub fn map1<F>(mut func: F)
where
F: FnMut(&mut Child),
{
let mut vec = vec![0; 16];
let x = &mut vec;
for i in 0..2 {
let offset = i * …Run Code Online (Sandbox Code Playgroud) 我有一个方法,我想给一个 Box,它包含一个实现该std::io::Write特征的结构。这是因为在我的程序中,我希望它写入标准输出,但在我的测试中,我希望它写入缓冲区并从该缓冲区生成一个字符串来验证我的程序。
我在我的程序中做了这样的事情:
let stdOutWriter = Box::new(io::stdout());
write_output(&mut results, stdOutWriter);
Run Code Online (Sandbox Code Playgroud)
其中 write_output 调用:
let mut wtr = csv::Writer::from_writer(writer);
Run Code Online (Sandbox Code Playgroud)
在我的测试中,我想调用:
let writer = Box::new(io::BufWriter::new(Vec::new()));
write_output(&mut results, writer).unwrap();
let bytes = Box::new(writer.into_inner().unwrap());
// I plan to validate this string later
let string = String::from_utf8(*bytes).unwrap();
Run Code Online (Sandbox Code Playgroud)
问题是 write_output 消耗了 writer,所以我无法调用 writer.into_inner()。所以我尝试将其更改为参考:
let mut writer = Box::new(io::BufWriter::new(Vec::new()));
write_output(&mut results, &mut writer).unwrap();
Run Code Online (Sandbox Code Playgroud)
现在我得到:
不匹配的类型预期可变引用
&mut Box<(dyn std::io::Write + 'static)>
发现可变引用&mut Box<BufWriter<Vec<u8>>>
我该如何解决这些问题?
编辑:
write_output 的签名是:
fn write_output(results: &HashMap<u16, ResultRecord>,writer: &mut Box<dyn io::Write>) -> …Run Code Online (Sandbox Code Playgroud) 我正在努力移植一个具有以下类型别名和函数的 Typescript 库:
type GlkTypedArray = Uint8Array | Uint32Array
get_buffer(buf: GlkTypedArray): number
Run Code Online (Sandbox Code Playgroud)
非常简单,它接受 aUint8Array或 a Uint32Array。
u8我现在尝试通过仅为and定义的特征在 Rust 中做同样的事情u32:
trait GlkInt: Sized {}
impl GlkInt for u8 {}
impl GlkInt for u32 {}
fn get_buffer(buf: &mut [dyn GlkInt]) -> u32;
Run Code Online (Sandbox Code Playgroud)
但不幸的是,它不允许这样做,说该特质不是Sized,尽管我认为特质定义意味着它会是。
error[E0277]: the size for values of type `dyn misc::GlkInt` cannot be known at compilation time
--> remglk/src/glkapi/streams.rs:18:29
|
18 | fn get_buffer(buf: &mut [dyn GlkInt]) -> u32;
| ^^^^^^^^^^^^ doesn't have …Run Code Online (Sandbox Code Playgroud) 我有这个代码
use std::iter::Step;
fn main() {
for i in mkiter(25, 20) {
println!("{}", i);
}
for i in mkiter(10, 23) {
println!("{}", i);
}
}
fn mkiter<T>(start: T, end: T) -> Box<dyn Iterator<Item = T>>
where
T: Step,
{
if start > end {
Box::new((end..=start).rev())
} else {
Box::new(start..=end)
}
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器告诉我我正在使用不稳定的功能:
error[E0658]: use of unstable library feature 'step_trait': recently redesigned
--> main.rs:1:5
|
1 | use std::iter::Step;
| ^^^^^^^^^^^^^^^
|
= note: see issue #42168 <https://github.com/rust-lang/rust/issues/42168> for more information …Run Code Online (Sandbox Code Playgroud) 我正在努力了解如何正确实现结构的任何类型的替代显示或特征。
\nstruct Fraction {\n numerator: u32,\n denominator: u32\n}\n\nimpl Fraction {\n fn unicode(&self) -> impl Display {\n // should I use named function or Closure?\n // Where does f come from?\n // can I re-use self?\n // How can I implement a trait that has multiple required functions or `type Output =`?\n fn fmt(&self, f: std::fmt::Formatter) -> std::fmt::Result {\n write!("{}\xe2\x81\x84{}", self.numerator, self.denominator)\n } // <- this returns `()`\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n这不起作用,因为fn fmt- 作为函数定义 - 不会返回任何内容。使用未命名的闭包:
impl Fraction …Run Code Online (Sandbox Code Playgroud)