简体   繁体   English

我如何封装 class 的私有可变 object,以便它可以通过不可变的 object 公开其属性?

[英]How can I encapsulate a private mutable object of a class such that it can expose its attributes publicly through an inmutable object?

To be more specific I am designing a Downloader Class that has as member variable a reference to an array of DownloadItem objects which represents resources that the user wants to download over the.network.更具体地说,我正在设计一个 Downloader Class,它的成员变量是对一组 DownloadItem 对象的引用,该对象表示用户想要通过 .network 下载的资源。 The idea is that a Downloader object will handle the details regarding connecting to the server that hosts the resource, fetching the file data/metadata and writing to disk while also exposing the state of the DownloadItems when queried.这个想法是下载器 object 将处理有关连接到托管资源的服务器、获取文件数据/元数据和写入磁盘的详细信息,同时在查询时还会公开 DownloadItems 的 state。

The DownloadItem stores information about the file such as filename, URL, file size, etc. plus other metadata such as the status, progress, when the download started, etc. Some of this information is not known before instantiation therefore the class itself should be mutable to allow for the Downloader object to modify it, but only the Downloader object that created it. DownloadItem 存储有关文件的信息,例如文件名、URL、文件大小等,以及其他元数据,例如状态、进度、下载开始时间等。其中一些信息在实例化之前是未知的,因此 class 本身应该是可变以允许下载器 object 修改它,但只有创建它的下载器 object。

In short I want the properties of the DownloadItem to be accessible through the Downloader object like so:简而言之,我希望 DownloadItem 的属性可以通过 Downloader object 访问,如下所示:

> DownloaderObj = Downloader()
> unique_id = DownloaderObj.download(url='https://path/to/resource', start_inmediate=False)
> print(DownloaderObj._download_queue)
  [<Class: DownloadItem url: https://path/to/resource filesize: -1>]
> DownloaderObj.start_download(unique_id)  # Handler thread updates metadata on the background
> print(DownloaderObj.get_download_by_id(unique_id).filesize)
  1024
> DowloaderObj.get_download_by_id(unique_id).filesize = 1024 # Should raise NotAllowed exception

One could have a lot of boilerplate code in the Downloader class that exposes those attributes but that increases the coupling between the two classes and makes the class less maintainable if I want to later extend the DownloadItem class to support other fields.如果我想稍后扩展 DownloadItem class 以支持其他字段,那么在 Downloader class 中可能有很多样板代码公开了这些属性,但这增加了两个类之间的耦合并使 class 的可维护性降低。 Any thoughts or ideas on how I can accomplish this?关于如何实现这一目标的任何想法或想法?

Side note: This problem is mostly for my own learning of OOP patterns and design choices so feel free to critique and add as much context as possible.旁注:这个问题主要是为了我自己学习 OOP 模式和设计选择,所以请随意批评并尽可能多地添加上下文。

I tried doing something like:我尝试做类似的事情:

class InmutableWrapper:
    def __init__(self, obj):
        self._obj = obj

    def __getattr__(self, val):
        return self._obj.__getattr__(val)

then returning InmutableDownloadItemObj = InmutableWrapper(DownloadItemObj) on the call to Downloader.get_download_by_id() but I could still do assignments which would be reflected when the property was queried:然后在调用 Downloader.get_download_by_id() 时返回 InmutableDownloadItemObj = InmutableWrapper(DownloadItemObj) 但我仍然可以进行分配,这将在查询属性时反映出来:

> print(Downloader.get_download_by_id(unique_id).filesize)
  1024
> Downloader.get_download_by_id(unique_id).filesize = 2    # Assigment goes through
> print(Downloader.get_download_by_id(unique_id)._obj.filesize) # Underlying object remains unchanged
  1024 
> print(Downloader.get_download_by_id(unique_id).filesize)
  2

One way to achieve this is to use the Proxy pattern.实现此目的的一种方法是使用代理模式。 The Proxy pattern is a structural design pattern that provides a surrogate or placeholder object for another object and controls access to it.代理模式是一种结构设计模式,它为另一个 object 提供代理或占位符 object 并控制对其的访问。

In this case, you can create a proxy class that wraps the DownloadItem object and exposes its attributes publicly.在这种情况下,您可以创建一个代理 class 来包装 DownloadItem object 并公开其属性。 The proxy class should have methods to get and set the attributes of the DownloadItem object, but should not allow any direct assignment to the DownloadItem object itself.代理 class 应具有获取和设置 DownloadItem object 属性的方法,但不应允许对 DownloadItem object 本身进行任何直接分配。

For example:例如:

class DownloadItemProxy:
    def __init__(self, download_item):
        self._download_item = download_item

    def get_filesize(self):
        return self._download_item.filesize

    def set_filesize(self, filesize):
        self._download_item.filesize = filesize

Then, in the Downloader class, you can return an instance of the DownloadItemProxy class instead of the DownloadItem object itself.然后,在 Downloader class 中,您可以返回 DownloadItemProxy class 的实例,而不是 DownloadItem object 本身。 This way, the Downloader class can still access and modify the DownloadItem object, but the user of the Downloader class will only be able to access and modify the attributes of the DownloadItem object through the proxy.这样,Downloader class仍然可以访问和修改DownloadItem object,但是Downloader class的用户将只能通过代理访问和修改DownloadItem object的属性。 Hope this helped.希望这有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过类访问类本身的弱引用对象? - How can I access the weakref object of the class itself through the class? 如何创建 object 并向其添加属性? - How can I create an object and add attributes to it? 如何将 object 的属性设置为 Python 中另一个对象的属性(另一个类)的值? - How can I set the attributes of an object to the value of another object's attribute (another class) in Python? 如果没有使用其属性,我如何避免类型检查python对象? - How can I avoid type checking a python object if its attributes aren't used? 每当访问对象的属性时,如何制作对象日志消息? - How can I make an object log messages whenever its attributes are accessed? 我可以定义如何处理访问 python object(而不仅仅是它的属性)吗? - Can I define how accessing python object (and not just its attributes) is handled? 我可以将 object 的属性隐式传递给 python 中的其他属性之一吗 - Can I implicitly pass attributes of an object to one of its other attributes in python 属性化的 object 能否访问其对象在 python 中的其他属性? - Can an attributed object access its object's other attributes in python? 如何在类属性中引用python对象的类方法? - How can a python object's classmethods be referred to inside the class attributes? 无法在“对象”类的实例上设置属性 - Can't set attributes on instance of "object" class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM