爱因斯坦是什么星座| 口舌生疮吃什么药最见效| 为什么会有阴虱子| 怀孕什么时候能测出来| 什么面粉最好| 头胀痛吃什么药| 晒伤用什么药| 信奥是什么| 什么是荠菜| 淋病吃什么药好的最快| 破处什么感觉| 膀胱炎是什么症状表现| 浪花像什么| 脚趾长痣代表什么意思| 血脂高吃什么好| 脖子疼是什么原因| 成人睡觉磨牙是什么原因| 马上风是什么意思| 五朵玫瑰花代表什么意思| 处女座是什么| 生殖疱疹用什么药效果好| 药敏试验是什么意思| 游走是什么意思| 乳腺增生吃什么药最好| 湿热体质适合喝什么茶| 为什么会高反| 观音土是什么| 狗狗假孕是什么症状| 补气是什么意思| 尿血是什么病| 529是什么意思| 哮喘用什么药| 吃榴莲对女人有什么好处| 胸部ct挂什么科| 孕期吃什么好| 七月开什么花| 肌酸是什么东西| 女人大腿粗代表什么| 乔其纱是什么面料| ipa啤酒是指什么| 余沧海为什么是两个人| 魄力是什么意思| 鹅蛋炒什么好吃| 化疗后吃什么增强免疫力| 覆水难收是什么意思| 汤姆猫是什么品种| 办护照照片有什么要求| 砥砺前行什么意思| 姝字五行属什么| 强心剂是什么药| 糖尿病可以吃什么水果| 兵马俑在什么地方| 麦五行属什么| 87年是什么命| 什么的花瓣| 乙肝核心抗体偏高是什么意思| 水黄是什么原因| 奔走相告的走是什么意思| 十二月十二日是什么星座| 什么是碱性磷酸酶高怎么回事| 贡眉是什么茶| 眼睛黑色部分叫什么| 孕妇缺营养吃什么补| 聚乙烯醇是什么材料| 什么叫过渡句| samedelman是什么牌子| 营长是什么军衔| 梦到抓了好多鱼是什么意思| 肾功能不全有什么症状| 5.23是什么星座| 什么是环切手术| 吃什么药能推迟月经| 梦见山体滑坡是什么意思| 小孩记忆力差什么原因| 中风的人吃什么好| 阿q精神是什么意思| 射手座属于什么星象| 吃什么养发| 小孩磨牙是什么原因| 山东登州府现在叫什么| 津字五行属什么| 吃什么去湿气| 肥胖去医院挂什么科| 胆碱能性荨麻疹吃什么药| 什么天什么什么| 加拿大用什么货币| 水保是什么| 前列腺增大是什么原因| 六月初一是什么日子| 我们都没错只是不适合是什么歌| 做包子用什么面粉好| 消化不良吃什么水果| 克氏针是什么| 公元400年是什么朝代| 何以笙箫默什么意思| 喝菊花水有什么好处| 鼻子干燥用什么药| 什么的猫| 非萎缩性胃炎伴糜烂是什么意思| 三岁打什么疫苗| bench是什么牌子| 龙和什么属相最配| 女性痔疮挂什么科室| 搀扶什么意思| ox什么意思| 肚子咕噜咕噜响是什么原因| 甲状腺功能挂什么科| 胎盘有什么用| 盯眝是什么意思| 白带异常吃什么药| 喝什么去湿气最好最快| 知柏地黄丸治什么病| 青海湖里面有什么鱼| 西洋参补什么| 蝙蝠属于什么类动物| 挑担是什么关系| 脉涩是什么意思| 鱼爱吃什么| 传染性单核细胞增多症是什么病| 画肖指什么生肖| 说话快的人什么性格| 肚子疼去医院挂什么科| 和可以组什么词| 脚没有力气是什么原因| 74年属什么生肖| cold什么意思| 色字头上一把刀什么意思| 什么药治便秘效果最好最快| skp什么意思| 干支是什么意思| 颈椎痛看什么科| 农历六月十九是什么日子| 秦国是现在的什么地方| 非诚勿扰是什么意思| 垂是什么意思| 什么东西越洗越脏脑筋急转弯| 武林外传的客栈叫什么| 头小脸小适合什么发型| 水落石出是什么生肖| 猴配什么生肖最好| 一个山一个见读什么| 夜郎自大是什么意思| 粉刺长什么样图片| 孕前检查挂什么科室| 去医院看嘴唇挂什么科| 胸椎退行性变什么意思| twins什么意思| 青春期指什么年龄段| 缺钾吃什么| 甲沟炎看什么科室| 决定的近义词是什么| 心脏房颤吃什么药最好| 巴甫洛夫的狗比喻什么| 什么方什么计| 胎儿左心室灶状强回声是什么意思| 喉咙发炎吃什么药| 2003年属羊的是什么命| 4月10号是什么星座| 女人卵巢保养吃什么好| 祎是什么意思| 什么是质子重离子治疗| 头层牛皮除牛反绒是什么意思| 前列腺炎有什么症状| 社保断了有什么影响| 毕业证有什么用| 踩指压板有什么好处| 宠物兔吃什么| 拉姆藏语什么意思| 云南属于什么地区| 兽性大发是什么生肖| 脸上长白斑是什么原因引起的| 与什么俱什么| 盆腔积液什么意思| 痛经吃什么| 胆囊是干什么用的| 双插头是什么意思| 面红耳赤是什么生肖| 护理是干什么的| 脑动脉硬化吃什么药| 血脂高有什么症状表现| 沐浴露什么牌子好| 刮宫是什么意思| 移植后可以吃什么水果| 什么是生化流产| 呆若木鸡的意思是什么| 小肚子胀是什么原因| 救星是什么意思| 女性尿道口有小疙瘩是什么原因| 心率过缓吃什么药| 3月30号是什么星座| 喝酒后头晕是什么原因| 鱼水之欢是什么意思| 台启是什么意思| 女人经期吃什么食物好| 维生素B1有什么副作用| 左侧肋骨下方疼痛是什么原因| 左大腿外侧麻木是什么原因| 农历六月初三是什么星座| 试管进周期是什么意思| 治疗静脉曲张有什么药| 带状疱疹有什么症状| 吃什么美容养颜抗衰老| 肠炎什么症状| 乐五行属什么| 椰子煲汤放什么材料| 什么是肺磨玻璃结节| 怀孕了吃什么药能流掉| 慢阻肺吃什么药最有效| 梦见摘菜是什么意思| 肝占位是什么意思| 脂肪肝吃什么好| 动员是什么意思| 鸟加衣念什么| 无性恋什么意思| everytime什么意思| 它是什么用英语怎么说| 七星鱼吃什么食物| 东倒西歪是什么意思| 感冒发烧吃什么好| 股票融是什么意思| 名垂千古是什么意思| 做大生化挂什么科| 巨蟹座跟什么星座最配| 一个点是什么意思| 女人湿气太重喝什么茶| 脑供血不足用什么药好| 肠炎吃什么药最好| 神经过敏是什么意思| 萱五行属什么| 胰尾显示不清什么意思| 看肺应该挂什么科| 14岁可以做什么工作| 心脾两虚吃什么药| 梦到别人怀孕了是什么意思| 文殊菩萨是管什么的| 一什么木瓜| 双子座是什么性格| 什么是格林巴利综合症| 梦见别人打架是什么意思| 右眼睛总跳是什么原因| 果粉是什么意思| 敌敌畏中毒用什么洗胃| 魂牵梦绕的意思是什么| 中央型肺ca是什么意思| 粉色裤子配什么上衣| momax是什么牌子| 洗耳恭听什么意思| 男人趴着睡觉说明什么| 西兰花是什么季节的蔬菜| 内脏吃多了有什么危害| 用什么洗脸可以祛斑| 公元前3000年是什么朝代| 梦见自己大出血是什么征兆| 隔离霜和防晒霜有什么区别| 招蚊子咬是什么原因| 审美疲劳是什么意思| 脾围是什么意思| 多吃木瓜有什么好处| 谈什么色变| 芽孢是什么| 痰涎壅盛是什么意思| 什么叫书签| 画蛇添足告诉我们什么道理| 老年斑长什么样| 百度
rfc:protectedlookup

杭州建德有了航空学院

Introduction

百度 (网页截图)  据美国odditycentral网站7月17日报道,俄罗斯金融寡头戈尔曼·史特里戈夫(GermanSterligov)24岁时就曾创建公司,并成为俄罗斯最富有的人之一。

This RFC proposes to eliminate an inconsistency in the way protected class members are resolved.

The fix to bug 37632 introduced a new visibility rule for protected methods. Prior to this fix, protected methods were visible only from their declaring class, ancestor classes and descendant classes. Subsequent to this fix, protected methods may be visible from sibling classes. Specifically, a protected method f declared in class C1 can be invoked from a context C2 if there is a class P which is an ancestor to both C1 and C2, and P declares a prototype of f. See the first code sample below for an illustration.

However, this rule is not applied consistently for all types of method invocation. For example, a method that is visible when invoked directly may become invisible when invoked as a callback. Furthermore, it does not apply at all to protected property lookups.

This RFC investigates 3 alternatives to improve consistency:

  • Option 1: Remove the new lookup rule.
  • Option 2: Ensure the new lookup rule is followed consistently.
  • Option 3: Modify the new lookup rule to better match the intuitive/documented meaning of 'protected', and ensure it is followed consistently.

Code Examples of the Inconsistencies

Illustration of the new lookup rule for direct invocation of instance and static methods

<?php
// Class P declares some protected members.
class P {
  protected function f() { echo 'P::f()'; }
  protected static function sf() { echo 'P::sf()'; } 
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
  protected function f() { echo 'C1::f()'; }
  protected static function sf() { echo 'C1::sf()'; } 
}
 
// Class C2 attempts to access protected members on its sibling C1.
class C2 extends P {
  public static function test() {
    $c1 = new C1;
    $c1->f();  // used to trigger fatal error, now prints C1::f()
    C1::sf();  // used to trigger fatal error, now prints C1::sf()
  }
}
 
C2::test();
?>

The new rule does not apply to properties (niether instance nor static)

<?php
// Class P declares some protected members.
class P {
  protected $p = 'P::$p';
  protected static $sp = 'P::$sp';
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
  protected $p = 'C1::$p';
  protected static $sp = 'C1::$sp';
}
 
// Class C2 attempts to access protected members on its sibling C1.
class C2 extends P {
  public static function test() {
    $c1 = new C1;
    echo $c1->p;  // Fatal error: Cannot access protected property C1::$p
    echo C1::$sp; // Fatal error: Cannot access protected property C1::$sp
  }
}
 
C2::test();
?>

The new rule does not apply to callbacks

<?php
// Class P declares some protected members.
class P {
  protected function f() { echo 'P::f()'; }
  protected static function sf() { echo 'P::sf()'; }  
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
  protected function f() { echo 'C1::f()'; }
  protected static function sf() { echo 'C1::sf()'; }    
}
 
// Class C2 attempts to access protected members on its sibling C1.
class C2 extends P {
  public static function test() {
    $c1 = new C1;
    var_dump(is_callable(array($c1, 'f'))); // false
    var_dump(is_callable(array('C1', 'sf'))); // false
    call_user_func(array($c1, 'f')); // Warning: [...] cannot access protected method C1::f()
    call_user_func(array('C1', 'sf')); // Warning: [...] cannot access protected method C1::sf()
  }
}
 
C2::test();
?> 

The new rule does not apply to implicit invocations of __clone()

<?php
// Class P declares some protected members.
class P {
  protected function __clone() { echo 'P::__clone()'; }
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
protected function __clone() { echo 'C1::__clone()'; }
}
 
// Class C2 attempts to access protected members on its sibling C1.
class C2 extends P {
  public static function test() {
    $c1 = new C1;
 	  clone $c1; // Fatal error: Call to protected C1::__clone() from context 'C2'
  }
}
 
C2::test();
?> 

The new rule does not apply to implicit invocations of __destruct()

<?php
// Class P declares some protected members.
class P {
  protected function __destruct() { echo 'P::__destruct()'; }
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
protected function __destruct() { echo 'C1::__destruct()'; }
}
 
// Class C2 attempts to access protected members on its sibling C1.
class C2 extends P {
  public static function test() {
    $c1 = new C1;
  } // Fatal error: Call to protected C1::__destruct() from context 'C2'
}
 
C2::test();
?> 

Some Details

The new lookup rule is implemented by using zend_get_function_root_class(function) when invoking zend_check_protected(class, context), e.g.:

   zend_check_protected(zend_get_function_root_class(fbc), EG(scope))

zend_get_function_root_class(f) returns the declaring class of the prototype that f overrides, or f 's declaring class if there is no such prototype. The inconsistency amongst method lookups were found by searching for calls to zend_check_protected() which do not make use of zend_get_function_root_class().

Properties do not keep pointers to the inherited properties that they shadow, so their “root class” cannot be determined in the same way.

Proposal

Option 1

Remove new rule: remove calls to zend_get_function_root_class().

Patch

Pros

  • Simple code change
  • Intuitive/documented meaning of protected is preserved: protected members are visible only from ancestor and descendant classes (not siblings).

Cons

<?php
// Class P declares some protected members.
class P {
  protected function f() { echo 'P::f()'; }
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
  protected function f() { echo 'C1::f()'; }
}
 
class C2 extends P {
  public static function test(P $liskov) {
    $liskov->f();
  }
}
 
C2::test(new P); // prints P::f()
C2::test(new C1); // Valid Liskov substitution. Should this fail?
?>

Removing the new rule causes a fatal error on the second invocation of C2::test(). If this is considered unacceptable, then this option should be rejected.

Option 2

If option 1 is dismissed due to the violation of LSP, it follows that the current rules for property access, callbacks, clone() and destruct() are also violations of LSP and should be fixed. This option ensures that zend_get_function_root_class() is used consistently for all protected method checks, and implements equivalent functionality for protected property checks.

Patch

Pros

  • Respects the Liskov Substitution Principle.

Cons

  • Non-trivial code change: requires that properties keep track of their root declaring class.
  • The protected modifier loses its intuitive/documented meaning, since protected members may be accessible from siblings.

Option 3

This approach is similar to option 2, but modifies the new rule slightly so as to preserve the intuitive meaning of the protected modifier. Lookups of protected members on sibling classes fall back to the declaration from the common ancestor class, if available. To illustrate:

<?php
// Class P declares some protected members.
class P {
  protected function f() { echo 'P::f()'; }
}
 
// Class C1 re-declares the inherited protected members.
class C1 extends P {
  protected function f() { echo 'C1::f()'; }
}
 
// Class C2 attempts to access protected members on its sibling C1.
class C2 extends P {
  public static function test() {
    $c1 = new C1;
    // C1::f() is not visible, so the call implicitly falls back to P::f().
    $c1->f(); // Prints 'P::f()'.
  }
}
?>

Patch

Pros

  • Respects the Liskov Substitution Principle.
  • Intuitive/documented meaning of protected is preserved: protected members are visible only from ancestor and descendent classes (not siblings).

Cons

  • Non-trivial code change
  • Possibly confusing at first, as code that reads C1::f() may in fact result in an invocation of P::f(). However, this behaviour would be comparable to existing behaviour when accessing re-declared private members of child classes. For example:
<?php
// Class P declares some private members.
class P {
  private function f() { echo 'P::f()'; }
  public static function test() {
    $c = new C;
    $c->f();  // falls back to P::f() prints P::f()
  }
}
 
// Class C1 re-declares the "inherited" private members.
class C extends P {
  private function f() { echo 'C::f()'; }
}
 
P::test();
?>

Appendix

Other potential LSP violations

If Option 1 is rejected on the grounds of a breach of LSP, then other arguable violations of LSP should be reviewed too. Below is a list of examples to be considered.

Private static methods

<?php
class P {
   private function f() { echo "In " . __METHOD__ . "\n"; }
   private static function sf() { echo "In " . __METHOD__ . "\n"; }
 
   static function test(P $liskov) {
      $class = get_class($liskov);
      echo "Instance method call on instance of $class: ";
      $liskov->f(); // if $liskov instanceof C, falls back to P::f()
      echo "Static method call on $class: ";
      $class::sf(); // if $liskov instanceof C, does not fall back to P::f() - fatal error.
   }
}
 
class C extends P {
   private function f() { echo "In " . __METHOD__ . "\n"; }
   private static function sf() { echo "In " . __METHOD__ . "\n"; }
}
 
P::test(new P);
P::test(new C); // Valid Liskov substitution - should this fail?
?>

Private static properties

<?php
class P {
   private $a = 'P::$a';
   private static $sa = 'P::$sa';
 
   static function test(P $liskov) {
      $class = get_class($liskov);
      echo "Instance property access on instance of $class: ";
      echo $liskov->a . "\n"; // if $liskov instanceof C, falls back to P::$a
      echo "Static property access call on $class: ";
      echo $class::$sa . "\n"; // if $liskov instanceof C, does not fall back to P::$sa - fatal error.
   }
}
 
class C extends P {
   private $a = 'C::$a';
   private static $sa = 'C::$sa';
}
 
P::test(new P);
P::test(new C); // Valid Liskov substitution - should this fail?
?>
rfc/protectedlookup.txt · Last modified: by 127.0.0.1

?
吃皮是什么意思 烊化是什么意思 胃胀是什么原因导致的 甲沟炎用什么药膏好 春捂秋冻指的是什么意思
做完肠镜需要注意什么 一什么所什么 siemens是什么品牌 脾胃不好吃什么食物可以调理 林可霉素主治什么病
高密度脂蛋白偏高是什么原因 一年一片避孕药叫什么 烫伤用什么药膏 什么的老虎 身上有红色的小红点是什么原因
眼底筛查是检查什么 吐露是什么意思 洋葱对肝脏有什么好处 喜欢出汗是什么原因 治疗hpv病毒用什么药
省委副书记是什么级别hcv9jop2ns5r.cn 头发干燥是什么原因hcv8jop8ns1r.cn 属猪的五行属什么yanzhenzixun.com 腰痛宁为什么晚上吃hcv7jop5ns5r.cn 焦糖色裤子配什么颜色上衣hcv8jop2ns0r.cn
命卦是什么意思hcv9jop6ns4r.cn nsa是什么意思hcv8jop5ns1r.cn 风湿性关节炎什么症状hcv9jop1ns1r.cn 白内障是什么原因引起的96micro.com 气血两虚是什么意思hcv9jop0ns1r.cn
左心房扩大是什么意思hcv8jop5ns1r.cn 曹植字什么jasonfriends.com 生化有什么症状和反应hcv9jop3ns1r.cn 东成西就是什么生肖hcv8jop8ns7r.cn newear是什么牌子hcv8jop4ns1r.cn
哺乳期感冒能吃什么药hcv8jop4ns6r.cn 什么是脑死亡hcv9jop5ns0r.cn 什么食物含磷高hcv8jop6ns3r.cn 上午十点是什么时辰hcv9jop1ns3r.cn 憋气是什么意思hcv9jop6ns7r.cn
百度