4 ms·
> In my experience, I've found that inheritance becomes a significant burden on projects, especially when using 3rd party libraries. I think inheritance is lik
by krylon 9y ago
> In my experience, I've found that inheritance becomes a significant burden on projects, especially when using 3rd party libraries.
I think inheritance is like any sufficiently powerful programming technique - with great power comes great potential for shooting yourself (and others) in the foot.
But there are situations where inheritance is an elegant and natural approach. They just are not very frequent.
Python's standard library for example has (or used to have at least, it's been a while since I looked) a framework for building network servers where you create a server by writing a class that inherits from two classes provided by the framework - one for the type of socket you'll be dealing with (TCP, UDP, Unix sockets), and one for defining how you want to do concurrency (forking, threading). The you just override one method that implements the actual request handler, and you're good to go. I consider that a clever and elegant use of inheritance.
Just to be clear, all in all, I tend to agree with you, and in my own code I use inheritance only very rarely. But I think that it's wrong to all-out condemn a programming technique just because it can be abused. It just means one has to carefully consider the advantages and disadvantages.
- brightball 9y agoOh, I'm definitely not condemning it. Honestly, I think it makes more sense when you are dealing with a GUI or desktop application where an object can be more representative of elements that a user is interacting with. For server side projects is where I've experienced it causing problems over project lifetimes. The maintainability complexity is where I've been bitten the worst.
- alphaalpha101 9y agoI disagree that this is elegant. import socket import threading import socketserver class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): def handle(self): data = str(self.request.recv(1024), 'ascii') cur_thread = threading.current_thread() response = bytes("{}: {}".format(cur_thread.name, data), 'ascii') self.request.sendall(response) class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass def client(ip, port, message): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect((ip, port)) sock.sendall(bytes(message, 'ascii')) response = str(sock.recv(1024), 'ascii') print("Received: {}".format(response)) if __name__ == "__main__": # Port 0 means to select an arbitrary unused port HOST, PORT = "localhost", 0 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) with server: ip, port = server.server_address # Start a thread with the server -- that thread will then start one # more thread for each request server_thread = threading.Thread(target=server.serve_forever) # Exit the server thread when the main thread terminates server_thread.daemon = True server_thread.start() print("Server loop running in thread:", server_thread.name) client(ip, port, "Hello World 1") client(ip, port, "Hello World 2") client(ip, port, "Hello World 3") server.shutdown() Why not this: def handle(request): data = str(request.recv(1024), 'ascii') cur_thread = threading.current_thread() response = bytes("{}: {}".format(cur_thread.name, data), 'ascii') request.sendall(response) and this: options = socketserver.ServerOptions( concurrency=socketserver.Threading, sockets=socketserver.TcpSockets) server = socketserver.Server((HOST, PORT), options) There's really not any use of inheritance here anyway: it's just a hack. It's such a hack that you need to inherit those two classes (ThreadingMixin and TCPServer) in that order, because one overrides a method of the other, and if you inherit them in the other order it just doesn't work. It might simplify the implementation, I don't know, but it definitely doesn't simplify the interface.