{
Let x= 6
} 此变量作用域中x的值是六,此变量作用域外x的值是5.
Struct user{name:string,id:i32};
let ltj = user{name:string::from”ltj”,id:110111198909238237};
let mut ltj = user{name:string::from”ltj”,id:110111198909238237};
ltj.id=0;
enum Option
Some(T),
None,
} 当某个变量可能为空值时,可以引入此枚举。
enum ipAdress
impl
fn getAdress
match Self {
ipAdress::v4(adr)=>adr,
ipAdress::v6(adr)=>adr
}
}
}
enum ipAdress
impl ipAdress
fn clearAdr(&mut Self) { v4.clear() }
}只有当ipadress 中T是string类型的时候,ipadress才能使用这个函数。
struct Point
x: T,
y: U,
}
impl
fn mixup
Point {
x: self.x,
y: other.y,
}
}
}
fn main() {
let p1 = Point { x: 5, y: 10.4 };
let p2 = Point { x: "Hello", y: 'c'};
let p3 = p1.mixup(p2);
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}
pub trait voice { fn call(&Self)->string;}
pub struct dark { callVoice:string }
impl voice for dark {
fn call(&Self)->string{
Self.callVoice
}
}
pub trait voice { fn theVoice(&Self)->string;
fn call(&Self)->string{
Self.theVoice()
}
}
pub struct dark { callVoice:string }
impl voice for dark {
fn theVoice(&Self)->string{
Self.callVoice
}
} 默认行为可以调用trait中的其他行为,不管其他行为有没有默认实现。如dark中实现了theVoice行为,那么我们就可以调用dark.call()行为。
Pub fn someFunc
Where T:Display+Clone
I:voice
U:debug{}
fn getfunc()->impl voice{ if 1{
dark{callVoice:string::from(“gaga”)
}
Else{
Chook{callVoice::string::from(“gegeda”)
}
}这是行不通的。因为trait不是类型,只是可共享的行为合集。而函数不能返回多个类型。17章介绍返回同一trait的多种类型的方法。
pub trait voice { fn theVoice(&Self)->string;
fn call(&Self)->string{
Self.theVoice()
}
}
pub struct dark
impl
fn new (a:T)->Self{
Self{a}
}
} 这个方法在t为任何类型时datk都可以调用。
Impl
Fn fly(&Self)->bool{
True
}
}而这个方法只有在t类型实现了Display trait时,dark才可以调用。
{
let r; // ---------+-- 'a
// |
{ // |
let x = 5; // -+-- 'b |
r = &x; // | |
} // -+ |
// |
println!("r: {}", r); // |
} // ---------+
rust不支持空值,这段代码中r的声明和初始化是分开的,如果在给定r一个值之前使用r,编译器会报错。继续看,r引用了x,但是在打印r的时候,x的生命周期已经结束,所以编译器会报错。接下来看生命周期。Rust的借用检查器把r的生命周期标记为’a,把x的生命周期标记为’b,然后检查到’a比‘b大,这不符合编译器的要求,编译器会报错,因为变量的生命周期应该比他的引用的生命周期要长。
#![allow(unused_variables)]
fn main() {
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
} 这个函数意味着参数x,y和返回值的生命周期存在某种关系。该关系表明返回值的生命周期应该是两个参数生命周期的公共部分。实际上这种关系在函数内部表现得并不明显。但是在函数调用的地方就很容易看出这其中的关系:
fn main() {
let string1 = String::from("long string is long");
let result;
{
let string2 = String::from("xyz");
result = longest(string1.as_str(), string2.as_str());
}
println!("The longest string is {}", result);
} 这段代码从程序的逻辑上看,是能够成功运行的,因为longest会返回string1的引用,所以在打印的时候result指向的string1没有被销毁。但是编译器仍然会报错。因为在函数longest中规定了返回值的生命周期是string1和string2的交集,也就是string2的生命周期。所以编译器认为在打印函数所在的代码段已经超出了result的生命周期范围,result不能被使用。
再看函数泛型生命周期:函数泛型生命周期表明了函数中引用之间的关系,编译器根据这种关系再通过传入的变量的生命周期,就可以确定每一个使用泛型生命周期的引用的真实生命周期。更深一步的说,函数的业务逻辑中隐含着各个引用的生命周期关系,rust只不过是要求程序员明确的把这种关系声明在函数的签名中而已。如下例子:
fn longest<'a>(x: &str, y: &str) -> &'a str {
let result = String::from("really long string");
result.as_str()
} 首先这个例子的函数签名并没有真实反应业务逻辑中引用的声明周期关系。返回值的生命周期应该和参数x指向的变量的生命周期相同。然而代码中的返回值的生命周期实际上是result的生命周期。其次,result的生命周期在函数结束时也结束了,即便不规定生命周期关系,这回导致返回的引用是一个垂悬引用,编译器会报错。如果函数返回一个有用所有权的变量就不会有问题。
struct ImportantExcerpt<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.')
.next()
.expect("Could not find a '.'");
let i = ImportantExcerpt { part: first_sentence };
} 这意味着结构体importantExcerpt的生命周期应该不大于其part字段的生命周期。而part字段的生命周期应该不大于first_sentence的生命周期。
60.生命周期省略规则:第一条规则是每一个是引用的参数都有它自己的生命周期参数。换句话说就是,有一个引用参数的函数有一个生命周期参数:fn foo<'a>(x: &'a i32)
,有两个引用参数的函数有两个不同的生命周期参数,fn foo<'a, 'b>(x: &'a i32, y: &'b i32)
,依此类推。
第二条规则是如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数:fn foo<'a>(x: &'a i32) -> &'a i32
。
第三条规则是如果方法有多个输入生命周期参数,不过其中之一因为方法的缘故为 &self
或 &mut self
,那么 self
的生命周期被赋给所有输出生命周期参数。
编译器一次对一个函数使用这三个规则,如果还是无法确定引用的真实生命周期,编译器会报错,让程序员自己声明引用的生命周期。
#![allow(unused_variables)]
fn main() {
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn level(&self) -> i32 {
3
}
}
} 方法level适用59条中规则一。
#![allow(unused_variables)]
fn main() {
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("Attention please: {}", announcement);
self.part
}
}
} 方法announce_and_return_part适用于59条规则三
#![allow(unused_variables)]
fn main() {
use std::fmt::Display;
fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
where T: Display
{
println!("Announcement! {}", ann);
if x.len() > y.len() {
x
} else {
y
}
}
} 由于’a也是泛型,所以他和T都可以放在尖括号中。只不过’a规定的是生命周期的关系。T规定的是参数类型的关系。