在Objective-C中,是否有必要覆盖子类的所有继承构造函数以添加自定义初始化逻辑?
例如,对于UIView具有自定义初始化逻辑的子类,以下内容是否正确?
@implementation CustomUIView
- (id)init {
self = [super init];
if (self) {
[self initHelper];
}
return self;
}
- (id)initWithFrame:(CGRect)theFrame {
self = [super initWithFrame:theFrame];
if (self) {
[self initHelper];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
[self initHelper];
}
return self;
}
- (void) initHelper {
// Custom initialization
}
@end
Run Code Online (Sandbox Code Playgroud) 我做了一个UIView具有固定框架的子类.那么,我可以覆盖init而不是initWithFrame:吗?例如:
- (id)init {
if ((self = [super initWithFrame:[[UIScreen mainScreen] bounds]])) {
self.backgroundColor = [UIColor clearColor];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
Xcode文档-initWithFrame:说:"如果以编程方式创建视图对象,则此方法是类的指定初始化程序UIView.子类可以重写此方法以执行任何自定义初始化,但必须super在其实现开始时调用."
"指定初始化程序"是什么意思?
我正在编写一个init脚本,它应该以不同于root的用户身份执行单个命令.这就是我目前正在做的事情:
sudo -u username command
这通常在Ubuntu/Debian上按预期工作,但在RHEL上,作为command挂起执行的脚本.
是否有另一种方法以另一个用户身份运行该命令?
(请注意,我不能使用lsb init函数,因为它们在RHEL/Centos 5.x上不可用.)
我正在创建一个http模块,在调试时我注意到一些东西,起初(至少)看起来像是奇怪的行为.
当我在httpmodule的init方法中设置断点时,我可以看到http模块初始化方法被多次调用,即使我只是启动了网站进行调试并发出了一个单一请求(有时它只被命中一次) ,其他时间多达10次).
我知道我应该期望HttpApplication的几个实例正在运行,并且每个http模块都将被创建,但是当我请求单个页面时,它应该由单个http应用程序对象处理,因此只触发关联一次的事件,但是它仍然会为每个请求多次触发事件,这是没有意义的 - 除了它必须在httpApplication中多次添加 - 这意味着它是每次调用的相同的httpmodule init方法而不是新的http应用程序每次碰到我的断点时都会被创建(请参阅底部的代码示例等).
这可能会出错?是因为我正在调试并在http模块中设置断点?
它已经注意到,如果我启动网站进行调试并快速跳过httpmodule中的断点,它只会触发一次init方法,而事件处理程序也是如此.如果我让它在断点处挂起几秒钟,则会多次调用init方法(看起来这取决于我在跨越断点之前等待多长时间).也许这可能是一些内置功能,以确保httpmodule已初始化,http应用程序可以提供请求,但它似乎也可能产生灾难性后果.
这似乎是合乎逻辑的,因为它可能正在尝试完成请求,因为我设置了断点,它认为出了问题,并尝试再次调用init方法?它可以处理请求吗?
但这是发生了什么,一切都很好(我只是猜测),还是一个真正的问题?
我特别关注的是,如果有什么东西让它挂在"生产/实时"服务器上几秒钟,那么很多事件处理程序都会通过init添加,因此每次对页面的请求都会突然激活事件处理程序几次.
此行为可能会迅速导致任何网站崩溃.
我查看了用于formauthentication和rolemanagermodule等的httpmodules的"原始".net代码,但我的代码与这些模块使用的代码不同.
我的代码看起来像这样.
public void Init(HttpApplication app)
{
if (CommunityAuthenticationIntegration.IsEnabled)
{
FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];
formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个如何在.NET框架的RoleManagerModule中完成它的示例
public void Init(HttpApplication app)
{
if (Roles.Enabled)
{
app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}
Run Code Online (Sandbox Code Playgroud)
有谁知道发生了什么?
(我只希望有人可以告诉我为什么会这样,并向我保证一切都很好):)
更新:
我试图缩小问题的范围,到目前为止,我发现被调用的Init方法总是在我的http模块的一个新对象上(与我之前想到的一致).
我似乎对于第一个请求(启动站点时)所有正在创建的HttpApplication对象及其模块都试图为第一个请求提供服务,因此所有HttpApplication都会触发正在添加的事件处理程序.我无法弄清楚为什么会这样.
如果我请求另一个页面,所有创建的HttpApplication(以及它们的无模块)将再次尝试提供请求,使其多次命中eventhandler.
但似乎如果我然后跳回到第一页(或另一个),只有一个HttpApplication将开始处理请求,一切都按预期 - 只要我不让它挂在断点.
如果我让它在断点处挂起它开始创建新的HttpApplication对象并开始添加HttpApplications(超过1)来提供/处理请求(已经在HttpApplication服务的过程中,当前在断点处停止) .
我想或希望它可能是一些帮助分发和处理负载和/或错误的智能"幕后"方式.但我不知道.我希望有些人可以向我保证它完全没问题,它应该如何?
这是一个双重问题,具有理论部分和实践部分:
子类化dict时:
class ImageDB(dict):
def __init__(self, directory):
dict.__init__(self) # Necessary??
...
Run Code Online (Sandbox Code Playgroud)
应该dict.__init__(self)被称为"安全"措施(例如,如果有一些重要的非平凡实施细节)?有一个风险,即与Python的未来版本的代码休息,如果dict.__init__()是不叫?我正在寻找做一件事或另一件事的根本原因,这里(实际上,呼叫dict.__init__()是安全的).
我的猜测是,当ImageDB.__init__(self, directory)调用时,self已经是一个新的空dict对象,因此无需调用dict.__init__(我确实希望dict为空,首先).它是否正确?
编辑:
以上基本问题背后更实际的问题如下.我在考虑继承dict,因为我会经常使用db [...]语法(而不是一直使用db.contents [...]); 对象的唯一数据(属性)确实是一个字典.我想向数据库添加一些方法(例如get_image_by_name(),或者get_image_by_code(),例如),并且只覆盖__init__(),因为图像数据库是由包含它的目录定义的.
总之,(实际)问题可能是:对于行为类似于字典的东西,什么是良好的实现,除了它的初始化是不同的(它只需要一个目录名),并且它有其他方法?
许多答案都提到了"工厂".所以我想这一切归结为:你是否继承dict,覆盖__init__()和添加方法,还是你写了一个返回dict的(工厂)函数,你要添加方法?我更倾向于选择第一个解决方案,因为工厂函数返回一个对象,其类型并不表示它有其他语义和方法,但你怎么看?
编辑2:
我从每个人的回答中得知,当新类"不是字典"时,将dict子类化并不是一个好主意,特别是当它的__init__方法不能采用与dict相同的参数时__init__(在"实际问题"中就是这种情况)以上).换句话说,如果我理解正确,那么共识似乎是:当您进行子类化时,所有方法(包括初始化)必须与基类方法具有相同的签名.这允许isinstance(subclass_instance,dict)保证subclass_instance.__init__()可以像dict.__init__()例如一样使用.
然后弹出另一个实际问题:除了初始化方法之外,应该如何实现类似dict的类?没有子类?这需要一些麻烦的样板代码,不是吗?
我希望这个问题不会被标记为primarily opinion-based,但是有一个客观的答案.
我已经阅读了介绍dumb-init,一个用于Docker容器的init系统,它广泛地描述了为什么以及如何使用它dumb-init.老实说,对于那些对Linux流程结构不太有经验的人来说,这听起来非常引人注目 - 如果你不使用它,感觉好像你做的事情完全错了dumb-init.
这就是我考虑在我自己的Docker镜像中使用它的原因...让我无法做到这一点的原因是我还没有找到使用它的官方Docker镜像.
如果dumb-init是这样重要的-为什么是明显地没有人使用它吗?我在这里错过了什么?
在驱动程序中,我经常看到使用这三种类型的init函数.
module_init()
core_initcall()
early_initcall()
Run Code Online (Sandbox Code Playgroud)
我想写init方法swift,这里我给了NSObject模型类Objective-C
-(id)initWithNewsDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
self.title = dictionary[@"title"];
self.shortDescription = dictionary[@"description"];
self.newsDescription = dictionary[@"content:encoded"];
self.link = dictionary[@"link"];
self.pubDate = [self getDate:dictionary[@"pubDate"]];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
我怎么能写这个方法swift?
关于多父继承,当我打电话给super.__init__,为什么不__init__调用parent2的函数?谢谢.
class parent(object):
var1=1
var2=2
def __init__(self,x=1,y=2):
self.var1=x
self.var2=y
class parent2(object):
var4=11
var5=12
def __init__(self,x=3,y=4):
self.var4=x
self.var5=y
def parprint(self):
print self.var4
print self.var5
class child(parent, parent2):
var3=5
def __init__(self,x,y):
super(child, self).__init__(x,y)
childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.parprint()
Run Code Online (Sandbox Code Playgroud)
输出是
9
10
5
11
12
Run Code Online (Sandbox Code Playgroud) 我熟悉为我自己的UIView子类创建XIB的大部分过程,但并不是所有的东西都适合我 - 这主要与IBOutlets链接有关.我可以让它们以迂回的方式工作.
我的设置是这样的:
我的init方法是我遇到问题的地方.
我尝试使用NSBundle mainBundle的'loadNibNamed'方法并将所有者设置为'self',希望我创建一个视图实例,它会自动将它的出口与我班级的出口相匹配(我知道)怎么做,我很小心).然后我想我想让'self'等于那个nib中索引0的子视图,而不是做
self = [super init];
Run Code Online (Sandbox Code Playgroud)
或类似的东西.
我觉得我在这里做错了,但是在线的例子在init方法中有类似的事情,但他们将子视图0分配给view属性并将其作为子项添加 - 但是那不是总共两个MyClass实例?一个基本上与IBOutlets无关,包含通过loadNibNamed实例化的子MyClass?或者充其量,它不是一个MyClass实例,带有一个额外的中间UIView,其中包含我最初想要的所有IBOutlets作为MyClass的直接子项吗?当涉及到像instanceOfMyClass.frame.size.width这样的事情时,这会带来轻微的烦恼,因为它返回0,当引入的子UIView返回我正在寻找的实际帧大小时.
我在做错的是我在init方法中搞乱了loadNibNamed吗?我应该做更像这样的事情吗?
MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];
Run Code Online (Sandbox Code Playgroud)
或者像这样?
MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0];
Run Code Online (Sandbox Code Playgroud)
在此先感谢您的任何帮助.
init ×10
uiview ×3
inheritance ×2
ios ×2
objective-c ×2
python ×2
subclass ×2
.net ×1
bash ×1
c# ×1
centos ×1
dictionary ×1
docker ×1
httpmodule ×1
iboutlet ×1
linux ×1
linux-kernel ×1
loadnibnamed ×1
oop ×1
rhel ×1
super ×1
swift ×1
uikit ×1