Мой комментарий к вашему вопросу объясняет, почему он не работает. Этот ответ показывает способ выполнить то, что вы просили, основываясь на вашем разъяснении, что MyChild
не должен распространяться MyParent
.
Это пример взлома, который заставляет его работать, используя тот факт, что php не если вы вызываете защищенные методы в других случаях, чем вы, если вы разделяете предок защищенного метода.
Мне пришлось изменить код, чтобы сделать его действительным php. __constructor
не является именем конструктора php.
hacky.php
<?php
class Observer
{
protected function callme()
{
echo 'I was called from ' . get_called_class(), PHP_EOL;
}
}
class MyParent extends Observer
{
public function createMyChild()
{
$this->callme(); // this is OK
return new MyChild ($this);
}
}
class MyChild extends Observer // hackey extends
{
private $myMyParent;
public function __construct($myMyParent)
{
$this->myMyParent = $myMyParent;
$this->myMyParent->callme();
}
}
$p = new MyParent;
$c = $p->createMyChild();
Результат:
$ php hacky.php
I was called from MyParent
I was called from MyParent
Вот мой собственный взгляд на проблему:
enum {
kUnitStringBinaryUnits = 1 << 0,
kUnitStringOSNativeUnits = 1 << 1,
kUnitStringLocalizedFormat = 1 << 2
};
NSString* unitStringFromBytes(double bytes, uint8_t flags){
static const char units[] = { '\0', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
static int maxUnits = sizeof units - 1;
int multiplier = (flags & kUnitStringOSNativeUnits && !leopardOrGreater() || flags & kUnitStringBinaryUnits) ? 1024 : 1000;
int exponent = 0;
while (bytes >= multiplier && exponent < maxUnits) {
bytes /= multiplier;
exponent++;
}
NSNumberFormatter* formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
if (flags & kUnitStringLocalizedFormat) {
[formatter setNumberStyle: NSNumberFormatterDecimalStyle];
}
// Beware of reusing this format string. -[NSString stringWithFormat] ignores \0, *printf does not.
return [NSString stringWithFormat:@"%@ %cB", [formatter stringFromNumber: [NSNumber numberWithDouble: bytes]], units[exponent]];
}
По умолчанию (если 0
передано для флагов
), выводятся единицы СИ (базовая десятка). Вы можете установить kUnitStringBinaryUnits
, чтобы выбрать двоичные (базовые два) блоки, подходящие для памяти, или kUnitStringOSNativeUnits
, чтобы тип блока выбирался автоматически в зависимости от версии ОС (до Leopard получает два, после -Леопард получает десятку). Параметр kUnitStringLocalizedFormat
форматирует строку на основе текущего языкового стандарта пользователя. Например:
unitStringFromBytes(1073741824, 0); // → "1.07 GB"
unitStringFromBytes(1073741824, kUnitStringBinaryUnits); // → "1 GB"
unitStringFromBytes(1073741824, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "1.07 GB" (In Mac OS 10.6)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12,345.68 YB" (In Mac OS 10.6, in the US)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12.345,68 YB" (In Mac OS 10.6, in Spain)
Вот вспомогательная функция, необходимая для модулей ОС:
BOOL leopardOrGreater(){
static BOOL alreadyComputedOS = NO;
static BOOL leopardOrGreater = NO;
if (!alreadyComputedOS) {
SInt32 majorVersion, minorVersion;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
Gestalt(gestaltSystemVersionMinor, &minorVersion);
leopardOrGreater = ((majorVersion == 10 && minorVersion >= 5) || majorVersion > 10);
alreadyComputedOS = YES;
}
return leopardOrGreater;
}
NSString *stringFromFileSize(NSInteger theSize)
{
/*
From http://snippets.dzone.com/posts/show/3038 with slight modification
*/
float floatSize = theSize;
if (theSize<1023)
return([NSString stringWithFormat:@"%i bytes",theSize]);
floatSize = floatSize / 1024;
if (floatSize<1023)
return([NSString stringWithFormat:@"%1.1f KB",floatSize]);
floatSize = floatSize / 1024;
if (floatSize<1023)
return([NSString stringWithFormat:@"%1.1f MB",floatSize]);
floatSize = floatSize / 1024;
return([NSString stringWithFormat:@"%1.1f GB",floatSize]);
}