我有一些继承自基类的类。通常使用c ++类,我习惯在子代中重写构造函数,然后调用父类。
在初始化子类而不重写子类时,Swift中是否有一种方法可以调用父构造函数?
internal class A {
init(aBool: Bool? = false) {
...
}
}
class B: A {
init(aString: String) {
...
}
}
以这两个类为例,我想使用A构造函数初始化B:
let obj = A(true)
答案 0 :(得分:12)
[S] ubclasses默认不继承其超类初始值设定项。但是,如果满足某些条件,则会自动继承超类初始值设定项。实际上,这意味着您不需要在许多常见场景中编写初始化程序覆盖,并且可以在安全的情况下以最小的努力继承您的超类初始化程序。
假设您为在子类中引入的任何新属性提供默认值,则适用以下两个规则:
规则1: 如果您的子类没有定义任何指定的初始值设定项,它会自动继承其所有超类指定的初始值设定项。
规则2: 如果您的子类提供了所有超类指定初始化器的实现 - 通过按照规则1继承它们,或者通过提供自定义实现作为其定义的一部分 - 那么它会自动继承所有超类便捷初始化器。
即使您的子类添加了更多便利初始值设定项,这些规则也适用。
这意味着什么?如果您将子类B
的初始值设定项设置为便捷初始值设定项,则B
应继承所有A
指定的初始值设定项。
class B: A {
convenience init(aString: String) { ... }
}
答案 1 :(得分:5)
如果您#include <iostream>
#include <cstring>
extern "C" {
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
}
int main(int argc, char *argv[])
{
if(argc != 3) {
std::cerr << "Run program as 'program ipaddress port'" << std::endl;
return -1;
}
auto &ipAddress = argv[1];
auto &portNum = argv[2];
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int gAddRes = getaddrinfo(ipAddress, portNum, &hints, &res);
if(gAddRes != 0) {
std::cerr << gai_strerror(gAddRes) << std::endl;
return -2;
}
std::cout << "Detecting addresses" << std::endl;
unsigned int numOfAddr = 0;
char ipStr[INET6_ADDRSTRLEN];
for(p = res; p != NULL; p = p->ai_next) {
void *addr;
std::string ipVer = "IPv0";
if(p->ai_family == AF_INET) {
ipVer = "IPv4";
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
++numOfAddr;
}
else {
ipVer = "IPv6";
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
++numOfAddr;
}
inet_ntop(p->ai_family, addr, ipStr, sizeof(ipStr));
std::cout << "(" << numOfAddr << ") " << ipVer << " : " << ipStr
<< std::endl;
}
if(!numOfAddr) {
std::cerr << "Found no host address to use" << std::endl;
return -3;
}
std::cout << "Enter the number of host address to bind with:" << std::endl;
unsigned int choice = 0;
bool madeChoice = false;
do {
std::cin >> choice;
if(choice > (numOfAddr + 1) || choice < 1) {
madeChoice = false;
std::cout << "Wrong choice, try again!" << std::endl;
}
else
madeChoice = true;
} while(!madeChoice);
p = res;
bool isIPv4 = true;
if(choice > 1) {
unsigned int temp = 1;
while(choice < temp) {
p = p->ai_next;
++temp;
}
if(p->ai_family == AF_INET) {
isIPv4 = true;
}
else
isIPv4 = false;
}
int sockFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(sockFD == -1) {
std::cerr << "Error while creating socket" << std::endl;
return -4;
}
int connectR = connect(sockFD, p->ai_addr, p->ai_addrlen);
if(connectR == -1) {
close(sockFD);
std::cerr << "Error while connecting socket" << std::endl;
return -5;
}
std::string message;
message.reserve(5);
auto len = message.capacity();
auto bytes_recv = recv(sockFD, &message.front(), len - 1, 0);
message[len] = 0;
close(sockFD);
freeaddrinfo(res);
std::cout << "Bytes recieved :" << bytes_recv << std::endl;
std::cout << message.c_str() << std::endl;
return 0;
}
初始化B
,则不会屏蔽原始convenience init
,您就可以执行此操作...
init
您必须小心默认或以其他方式设置所有属性,但是......
或者,您可以class A {
var b: Bool? = nil
init(aBool: Bool? = false) {
self.b = aBool
}
}
class B: A {
var s: String? = nil
convenience init(aString: String) {
self.init(aBool: false)
self.s = aString
}
}
let obj1 = A(aBool: true) // obj1 is now an A, obviously.
let obj2 = B(aBool: true) // obj2 is now a B
override
中的原始init
,然后只需致电B
。