ฉันดู Pycon ของ Raymond Hettinger พูดว่า "Super Considered Super" และเรียนรู้เล็กน้อยเกี่ยวกับ PROON ของ MRO (Method Resolution Order) ซึ่งทำให้ชั้นเรียนเป็น "ผู้ปกครอง" ในลักษณะเชิงเส้น เราสามารถใช้สิ่งนี้เพื่อประโยชน์ของเราเช่นในรหัสด้านล่างเพื่อทำการฉีดพึ่งพา ตอนนี้ตามธรรมชาติฉันต้องการใช้superสำหรับทุกสิ่ง!
ในตัวอย่างด้านล่างที่Userระดับประกาศอ้างอิงมันโดยการสืบทอดจากทั้งสองและLoggingService UserServiceนี่ไม่ใช่สิ่งที่พิเศษเป็นพิเศษ ส่วนที่น่าสนใจคือเราสามารถใช้การแก้ไขวิธีสั่งซื้อยังจำลองการอ้างอิงในระหว่างการทดสอบหน่วย โค้ดด้านล่างนี้สร้างสิ่งMockUserServiceที่สืบทอดมาUserServiceและนำเสนอวิธีการที่เราต้องการจำลอง validate_credentialsในตัวอย่างด้านล่างเราให้การดำเนินการของ เพื่อที่จะได้MockUserServiceจัดการกับการโทรใด ๆ ที่validate_credentialsเราจำเป็นต้องวางไว้ก่อนUserServiceใน MRO นี้ทำได้โดยการสร้างชั้นห่อหุ้มรอบUserเรียกว่าMockUserและมีมันสืบทอดมาจากและUserMockUserService
ตอนนี้เมื่อเราทำMockUser.authenticateและในทางกลับกันการเรียกใช้มาsuper().validate_credentials() MockUserServiceก่อนUserServiceในการสั่งซื้อวิธีการแก้ปัญหาและเนื่องจากมีการใช้งานที่เป็นรูปธรรมของvalidate_credentialsการดำเนินการนี้จะถูกนำมาใช้ Yay - เราประสบความสำเร็จUserServiceในการทดสอบหน่วยการเรียนรู้ของเรา พิจารณาว่าUserServiceอาจทำการโทรผ่านเครือข่ายหรือฐานข้อมูลราคาแพง - เราเพิ่งลบปัจจัยแฝงของสิ่งนี้ นอกจากนี้ยังไม่มีความเสี่ยงในการUserServiceสัมผัสข้อมูลสด / กระทุ้ง
class LoggingService(object):
    """
    Just a contrived logging class for demonstration purposes
    """
    def log_error(self, error):
        pass
class UserService(object):
    """
    Provide a method to authenticate the user by performing some expensive DB or network operation.
    """
    def validate_credentials(self, username, password):
        print('> UserService::validate_credentials')
        return username == 'iainjames88' and password == 'secret'
class User(LoggingService, UserService):
    """
    A User model class for demonstration purposes. In production, this code authenticates user credentials by calling
    super().validate_credentials and having the MRO resolve which class should handle this call.
    """
    def __init__(self, username, password):
        self.username = username
        self.password = password
    def authenticate(self):
        if super().validate_credentials(self.username, self.password):
            return True
        super().log_error('Incorrect username/password combination')
        return False
class MockUserService(UserService):
    """
    Provide an implementation for validate_credentials() method. Now, calls from super() stop here when part of MRO.
    """
    def validate_credentials(self, username, password):
        print('> MockUserService::validate_credentials')
        return True
class MockUser(User, MockUserService):
    """
    A wrapper class around User to change it's MRO so that MockUserService is injected before UserService.
    """
    pass
if __name__ == '__main__':
    # Normal useage of the User class which uses UserService to resolve super().validate_credentials() calls.
    user = User('iainjames88', 'secret')
    print(user.authenticate())
    # Use the wrapper class MockUser which positions the MockUserService before UserService in the MRO. Since the class
    # MockUserService provides an implementation for validate_credentials() calls to super().validate_credentials() from
    # MockUser class will be resolved by MockUserService and not passed to the next in line.
    mock_user = MockUser('iainjames88', 'secret')
    print(mock_user.authenticate())สิ่งนี้ให้ความรู้สึกที่ค่อนข้างฉลาด แต่นี่เป็นการใช้งานที่ดีและถูกต้องของการรับมรดกที่หลากหลายและการสั่งซื้อวิธีการแก้ปัญหาของ Python หรือไม่? เมื่อฉันคิดเกี่ยวกับการรับมรดกในทางที่ผมได้เรียนรู้ OOP กับ Java รู้สึกนี้ผิดอย่างสมบูรณ์เพราะเราไม่สามารถพูดได้Userเป็นUserServiceหรือเป็นUser LoggingServiceเมื่อคิดอย่างนั้นการใช้การสืบทอดวิธีที่โค้ดด้านบนใช้นั้นไม่สมเหตุสมผลเลย หรือมันคืออะไร? ถ้าเราใช้การถ่ายทอดทางพันธุกรรมเพียงอย่างเดียวเพื่อให้นำรหัสมาใช้ใหม่และไม่คิดในแง่ของความสัมพันธ์ระหว่างผู้ปกครอง -> เด็กสิ่งนี้ก็ไม่ได้เลวร้ายนัก
ฉันทำผิดหรือเปล่า?