这个问题是用伪 PHP 编写的,但我真的不介意我用什么语言得到答案(Ruby :-P 除外),因为这纯粹是假设性的。事实上,PHP 很可能是执行此类逻辑的最糟糕的语言。不幸的是,我以前从未这样做过,所以我无法提供真实世界的示例。因此,假设的答案是完全可以接受的。
基本上,我有很多执行任务的对象。对于此示例,假设每个对象都是一个从 Internet 下载文件的类。每个对象将下载不同的文件,并且下载是并行运行的。显然,某些对象可能会先于其他对象完成下载。数据的实际抓取可能在线程中运行,但这与这个问题无关。
所以我们可以这样定义对象:
class DownloaderObject() {
var $url = '';
var $downloading = false;
function DownloaderObject($v){ // constructor
$this->url = $v;
start_downloading_in_the_background(url=$this->$url, callback=$this->finished);
$this->downloading = true;
}
function finished() {
save_the_data_somewhere();
$this->downloading = false;
$this->destroy(); // actually destroys the object
}
}
好的,所以我们有很多这样的对象在运行:
$download1 = new DownloaderObject('http://somesite.com/latest_windows.iso');
$download2 = new DownloaderObject('http://somesite.com/kitchen_sink.iso');
$download3 = new DownloaderObject('http://somesite.com/heroes_part_1.rar');
我们可以将它们存储在一个数组中:
$downloads = array($download1, $download2, $download3);
所以我们有一个充满下载的数组:
array(
1 => $download1,
2 => $download2,
3 => $download3
)
我们可以像这样遍历它们:
print('Here are the downloads that are running:');
foreach ($downloads as $d) {
print($d->url . "\n");
}
好的,现在假设下载 2 完成,并且对象被销毁。现在我们应该在数组中有两个对象:
array(
1 => $download1,
3 => $download3
)
但是阵中有一个洞!密钥 #2 未被使用。此外,如果我想开始新的下载,不清楚将下载插入到数组的哪个位置。以下可以工作:
$i = 0;
while ($i < count($downloads) - 1) {
if (!is_object($downloads[$i])) {
$downloads[$i] = new DownloaderObject('http://somesite.com/doctorwho.iso');
break;
}
$i++;
}
然而,这是非常低效的(并且while $i++
循环是nooby)。所以,另一种方法是保留一个计数器。
function add_download($url) {
global $downloads;
static $download_counter;
$download_counter++;
$downloads[$download_counter] = new DownloaderObject($url);
}
这会起作用,但我们仍然会在数组中找到漏洞:
array(
1 => DownloaderObject,
3 => DownloaderObject,
7 => DownloaderObject,
13 => DownloaderObject
)
太丑了 然而,这样可以接受吗?是否应该对数组进行“碎片整理”,即重新排列键以消除空格?
还是我应该注意另一种程序结构?我想要一个结构,我可以添加东西,从中删除东西,引用变量中的键,迭代等等,这不是一个数组。这样的事情存在吗?
我已经编码多年了,但是这个问题多年来一直困扰着我,我仍然不知道答案。这对一些程序员来说可能很明显,但对我来说却非常重要。