用CSS在不破坏一张图的内容的情况下 怎么把它放到比它小的div中
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用CSS在不破坏一张图的内容的情况下 怎么把它放到比它小的div中相关的知识,希望对你有一定的参考价值。
既然是比图片小的div,说明你设置了固定的宽高。把图片宽高设置成百分比,如果想图片保持宽高比例,宽高设置一个就行
img
width:100%;
height:100%;
参考技术A 宽高用百分比,只设置一个就行 不然会变形 参考技术B 给那个小的div设施一个宽高,图片100%显示,高度自动就行了
如何在不破坏封装的情况下返回对 RefCell 内某些内容的引用?
【中文标题】如何在不破坏封装的情况下返回对 RefCell 内某些内容的引用?【英文标题】:How do I return a reference to something inside a RefCell without breaking encapsulation? 【发布时间】:2015-06-06 17:45:00 【问题描述】:我有一个具有内部可变性的结构。
use std::cell::RefCell;
struct MutableInterior
hide_me: i32,
vec: Vec<i32>,
struct Foo
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
impl Foo
pub fn get_items(&self) -> &Vec<i32>
&self.interior.borrow().vec
fn main()
let f = Foo
interior: RefCell::new(MutableInterior
vec: Vec::new(),
hide_me: 2,
),
;
let borrowed_f = &f;
let items = borrowed_f.get_items();
产生错误:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 |
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32>
16 | | &self.interior.borrow().vec
17 | |
| |_____^
问题是我不能在Foo
上拥有一个返回借用vec
的函数,因为借用的vec
仅在Ref
的生命周期内有效,但Ref
可以使用立即超出范围。
我认为Ref
必须坚持because:
RefCell<T>
使用 Rust 的生命周期来实现“动态借用”,这是一个可以声明对内部值的临时、独占、可变访问的过程。RefCell<T>
s 的借用是在“运行时”跟踪的,这与 Rust 的本地引用类型不同,后者在编译时完全静态跟踪。因为RefCell<T>
借用是动态的,所以可以尝试借用一个已经可变借用的值;发生这种情况时会导致任务恐慌。
现在我可以写一个这样的函数来返回整个内部:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
但是,这可能会向Foo
公开真正私有的实现细节的字段(在此示例中为MutableInterior.hide_me
)。
理想情况下,我只想公开vec
本身,可能带有一个守卫来实现动态借用行为。这样来电者就不必知道hide_me
。
【问题讨论】:
【参考方案1】:您可以创建一个类似于 RefCell::borrow()
返回的 Ref<'a,T>
守卫的新结构,以包装此 Ref
并避免其超出范围,如下所示:
use std::cell::Ref;
struct FooGuard<'a>
guard: Ref<'a, MutableInterior>,
然后,您可以为它实现Deref
trait,这样它就可以像&Vec<i32>
一样使用:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b>
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32>
&self.guard.vec
之后,更新您的 get_items()
方法以返回 FooGuard
实例:
impl Foo
pub fn get_items(&self) -> FooGuard
FooGuard
guard: self.interior.borrow(),
Deref
会变魔术:
fn main()
let f = Foo
interior: RefCell::new(MutableInterior
vec: Vec::new(),
hide_me: 2,
),
;
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
【讨论】:
这是唯一/惯用的方法吗?似乎有点麻烦......虽然我想代替 getItems() 方法,您可以直接借用块中的内部结构,然后它会超出范围(或其他东西......) @Norcalli 在RefCell
的特定情况下,当引用超出范围时需要通知对象(这就是Ref
的析构函数所做的)。在这里,我们需要保留这种行为(OP的错误是由于Ref
实例被过早丢弃),从而对其进行封装。【参考方案2】:
您可以使用Ref::map
(从Rust 1.8 开始),而不是创建一个全新的类型。这与Levans' existing answer 的结果相同:
use std::cell::Ref;
impl Foo
pub fn get_items(&self) -> Ref<'_, Vec<i32>>
Ref::map(self.interior.borrow(), |mi| &mi.vec)
您还可以使用 impl Trait
等新功能从 API 中隐藏 Ref
:
use std::cell::Ref;
use std::ops::Deref;
impl Foo
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_
Ref::map(self.interior.borrow(), |mi| &mi.vec)
【讨论】:
如果你正在实现 std::ops::Index 特征,而不是 get_item ,这需要你返回 &Self::Output 。据我所知,返回 std::cell::Ref 不会满足特征要求。有没有办法针对该特征进行内部可变性? 其实我找到了一种使用 UnsafeCell 的方法,所以我认为这可能就足够了。 @DanielV Implementing Index trait to return a value that is not a reference。我不相信UnsafeCell
实现,因为它很可能会引入内存不安全。【参考方案3】:
您可以将Vec
包装在Rc
中。
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior
hide_me: i32,
vec: Rc<Vec<i32>>,
struct Foo
interior: RefCell<MutableInterior>,
impl Foo
pub fn get_items(&self) -> Rc<Vec<i32>>
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
fn main()
let f = Foo
interior: RefCell::new(MutableInterior
vec: Rc::new(Vec::new()),
hide_me: 2,
),
;
let borrowed_f = &f;
let items = borrowed_f.get_items();
当您需要改变Vec
时,使用Rc::make_mut
来获得对Vec
的可变引用。如果还有其他Rc
s 引用Vec
,make_mut
会将Rc
与其他Rc
s 分离,克隆Vec
并更新自身以引用新的Vec
,然后给你一个可变的引用。这确保了其他 Rc
s 中的值不会突然改变(因为 Rc
本身不提供内部可变性)。
【讨论】:
以上是关于用CSS在不破坏一张图的内容的情况下 怎么把它放到比它小的div中的主要内容,如果未能解决你的问题,请参考以下文章
在不破坏 DropArea 的情况下拒绝拖放到 DropArea 中的外部文件
如何在不破坏图像、CSS 和 JavaScript 的情况下实现友好的 URL? [关闭]