今天是个好日子!
我的问题是:我需要在类中重载标准get和设置静态变量...但是在php中没有提供这样的功能...它在2008年被问到但仍未实现...同样适用于readonly ...
我的问题:有没有办法让静态属性可以从外部读取,但是可以防止修改?
echo aaa::$qwe; //<--- echoes value of $qwe
aaa::$qwe = '666'; //<--- throws an error because variable is protected from modification
Run Code Online (Sandbox Code Playgroud)
我不能使用const,因为一些变量包含数组.
也许有一些解决方法?
是的,我知道我可以把它变成aaa :: Get('qwe'),但这并不好......
假设我们有一个包含多个受保护和/或公共方法的类.我需要在每次调用方法时执行检查.每次调用方法时我都可以检查:
class Object
{
// Methods
}
$o = new Object();
if($mayAccess) $o->someMethod();
Run Code Online (Sandbox Code Playgroud)
要么
if($mayAccess) $this->someMethod();
Run Code Online (Sandbox Code Playgroud)
但我希望开发人员不必考虑它,也不要写它.我已经考虑过使用__call来做:
class Object
{
public function __call($methodName, $args)
{
if($mayAccess) call_user_func_array($this->$methodName, $args);
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我从类中调用该方法,则不会调用__call,因为它仅在调用非可见方法时才起作用.
是否有一种干净的方法来隐藏内部和外部呼叫的检查?再次,目标是确保开发人员在调用方法时不会忘记这样做.
提前致谢 :)
EDIT :
Run Code Online (Sandbox Code Playgroud)
我有另一种方法:
class Object
{
public function __call($methodName, $args)
{
if($mayAccess) call_user_func_array($methodName, $args);
}
}
function someMethod() { }
Run Code Online (Sandbox Code Playgroud)
但我将无法使用$ this,这意味着没有受保护的方法,我确实需要.
来自Java,我只有几次假期访问PHP.看看魔术获取和设置方法,我(受Java影响)的肚子开始受到伤害:看起来好像是直接访问属性(当然,你实际上是在使用__get和__set).
所以 - 除了你需要编写的代码少之外,使用magic getter和setter方法代替传统的getX()/ setX()方法有什么好处吗?我应该在编写PHP时开始使用它们吗?
谢谢,最好!
我想知道是否有办法向变量添加类似更改侦听器的内容.我所说的最简单的例子就是沿着这些方向发挥作用;
// Start with a variable
$variable = "some value";
// Define a listener
function myChangeListener($variable) {
// encode with json_encode and send in cookie
}
// Add my listener to the variable
addListenerToVariable(&$variable, 'myChangeListener');
// Change the variables value, triggering my listener
$variable = "new value";
Run Code Online (Sandbox Code Playgroud)
现在你可能会问为什么在世界上我甚至需要打扰这种方法,为什么不只是创建一个函数来设置cookie.答案是我有一个&__get($var)魔术方法返回对多维数组元素的引用,我希望使用这样的东西来检测数组元素或其中一个子元素是否已被编辑,然后发送一个cookie,如果有的话.希望的结果会像这样起作用;
$cookies->testArray["test"] = "newValue";
// This would send the cookie 'testArray' with the value '{"test":"newValue"}'
Run Code Online (Sandbox Code Playgroud)
老实说,我认为这是完全不可能的,如果我是正确的,我道歉.但我昨天刚刚学会了如何正确使用引用,所以我想在完全注销这个想法之前我会问.
感谢我得到的任何回复,无论是我希望的还是我期望的.
编辑:
为了更加清晰,这里是我想要完成的一个示例类;
class MyCookies {
private $cookies = array();
private $cookieTag = "MyTag";
public …Run Code Online (Sandbox Code Playgroud) 我正在尝试了解使用更新python字典的确切机制d[key] += diff.我有一些辅助类来跟踪魔术方法调用:
class sdict(dict):
def __setitem__(self, *args, **kargs):
print "sdict.__setitem__"
return super(sdict, self).__setitem__(*args, **kargs)
def __delitem__(self, *args, **kargs):
print "sdict.__delitem__"
return super(sdict, self).__delitem__(*args, **kargs)
def __getitem__(self, *args, **kargs):
print "sdict.__getitem__"
return super(sdict, self).__getitem__(*args, **kargs)
def __iadd__(self, *args, **kargs):
print "sdict.__iadd__"
return super(sdict, self).__iadd__(*args, **kargs)
def __add__(self, *args, **kargs):
print "sdict.__add__"
return super(sdict, self).__add__(*args, **kargs)
class mutable(object):
def __init__(self, val=0):
self.value = val
def __iadd__(self, val):
print "mutable.__iadd__"
self.value = self.value + val
return self
def __add__(self, val): …Run Code Online (Sandbox Code Playgroud) 例如,我有以下内容:
class A{
__invoke(){
// return an instance of class A itself
}
}
Run Code Online (Sandbox Code Playgroud)
我可以这样做吗?
new A()()()()... or (new A())()()()...
Run Code Online (Sandbox Code Playgroud)
这是什么解释?假设PHP版本比5.4更新
好吧,我可以再解释一下为什么我要问:我正在使用ganon.php这是一个开源的html dom解析器.它使用类似$ html_node('child_tag')的语法来返回另一个子$ html_node,其中$ html_node是类HTML_NODE的对象实例.所以我在想是否可以使用链接在嵌套的html dom结构中进行选择.
我有一个类似于这个(强烈简化)示例的包装类:
class wrap(object):
def __init__(self):
self._data = range(10)
def __getitem__(self, key):
return self._data.__getitem__(key)
Run Code Online (Sandbox Code Playgroud)
我可以像这样使用它:
w = wrap()
print w[2] # yields "2"
Run Code Online (Sandbox Code Playgroud)
我以为我可以通过改变这个来优化和摆脱一个函数调用:
class wrap(object):
def __init__(self):
self._data = range(10)
self.__getitem__ = self._data.__getitem__
Run Code Online (Sandbox Code Playgroud)
但是,我收到了
TypeError:'wrap'对象不支持索引
对于print w[2]后一版本的行.
直接调用该方法,即print w.__getitem__(2)在两种情况下都有效...
为什么赋值版本不允许索引?
说我已经建立包含一个库Foo类,与一些魔术方法的支持,说__add__()和__radd__():
>>> class Foo(object):
... def __add__(self, rhs):
... print("Foo.__add__", rhs)
... def __radd__(self, lhs):
... print("Foo.__radd__", lhs)
...
>>> foo = Foo()
>>> foo + 3
Foo.__add__ 3
>>> 3 + foo
Foo.__radd__ 3
Run Code Online (Sandbox Code Playgroud)
在计算时3 + foo,python首先调用type(3).__add__(3, foo),但是当它返回时NotImplemented,它会回退到type(foo).__radd__(foo, 3):
>>> type(3).__add__(3, foo)
NotImplemented
Run Code Online (Sandbox Code Playgroud)
我希望开发人员能够在我的库之上构建库,比如一个包含类的库Bar,我希望它们能够完全控制.特别是,我想实现一些机制,让其他库决定是否foo + bar应该调用foo.__add__(bar)或bar.__radd__(foo).
我看到NumPy使用该__array_priority__方案解决了这个问题.但这似乎引起了一些令人头疼的问题(考虑到问题和问题的数量).还有其他最佳做法吗?
这里我定义了不可变类 str。在 新方法中,我将“hello”等实例的值更改为大写。当我们可以在init中定义 upper 时,为什么要使用new来实现呢?
class Upperstr(str):
def __new__(cls,value=""):
print(cls)
print(value)
return str.__new__(cls,value.upper())
# def __init__(self,m1):
# self.m1 = m1.upper()
u = Upperstr("hello")
print(u)
Run Code Online (Sandbox Code Playgroud)
New 用于创建类实例。新方法还有哪些其他用途?
例如,请考虑以下情况:
class FooMeta(type):
def __len__(cls):
return 9000
class GoodBar(metaclass=FooMeta):
def __len__(self):
return 9001
class BadBar(metaclass=FooMeta):
@classmethod
def __len__(cls):
return 9002
len(GoodBar) -> 9000
len(GoodBar()) -> 9001
GoodBar.__len__() -> TypeError (missing 1 required positional argument)
GoodBar().__len__() -> 9001
len(BadBar) -> 9000 (!!!)
len(BadBar()) -> 9002
BadBar.__len__() -> 9002
BadBar().__len__() -> 9002
Run Code Online (Sandbox Code Playgroud)
问题在于len(BadBar)返回 9000 而不是 9002,这是预期的行为。
这种行为(在某种程度上)记录在Python 数据模型 - 特殊方法查找中,但它没有提到任何有关类方法的内容,而且我并不真正理解与@classmethod装饰器的交互。
除了明显的元类解决方案(即替换/扩展FooMeta)之外,是否有一种方法可以覆盖或扩展元类函数,以便len(BadBar) -> 9002?
为了澄清,在我的特定用例中,我无法编辑元类,并且我不想对其进行子类化和/或创建我自己的元类,除非这是唯一可能的方法。