LSP(Liskov替代原理)如何工作

时间:2019-02-05 17:12:06

标签: java object parent substitution

LSP(Liskov替代原理)指出: 该原理定义了超类的对象可以用其子类的对象替换,而不会破坏应用程序。

例如:

func didJoinGroupConvo(groupConvoId: String) {
    guard !joinedGroupConvoIds.contains(groupConvoId) else { return }
    joinedGroupConvoIds.append(groupConvoId)

    guard
        let row = suggestedGroups.firstIndex(where: { $0.id == groupConvoId }),
        let cell = tableView.cellForRow(at: IndexPath(row: row, section: 0)) as? GroupMessageSettingsUserCell,
        let currentUser = PFUser.current(),
        let currentUserId = currentUser.objectId,
        let currentUsername = currentUser.username
    else { return }

    // If I comment out starting here, it won't block. Otherwise, as long as it's doing this call, it will block the UI
    DispatchQueue.global(qos: .background).async {
        Firestore.Collections.groupConvos.path
            .document(groupConvoId)
            .updateData([
                kMemberIds: FieldValue.arrayUnion([currentUserId]),
                kUpdatedAt: FieldValue.serverTimestamp()
            ]) { [weak self] error in
                guard let self = self else { return }

                if error == nil {
                    guard row < self.suggestedGroups.count else { return }
                    let groupConvo = self.suggestedGroups[row]

                    NotificationCenter.default.post(name: NSNotification.Name("Joined"), object: groupConvo)

                    DispatchQueue.main.async {
                        cell.nameLabel?.text = "\(groupConvo.memberCount + 1) members"
                    }

                    let message = GroupMessage.createJoinLeftSystemMessage(joined: true, groupName: groupConvo.groupName, username: currentUsername)
                    message.saveMessage(to: groupConvo, withMessageType: .system) { _ in
                        self.delegate?.didJoinGroup(withGroupId: groupConvoId)
                    }
                }
        }
    }
}

以上语句在内存级别如何工作(如何工作)? 创建“汽车”类是为了实现汽车具有但普通车辆缺乏的特定行为。

如何将“ BMW”对象称为车辆类别?

2 个答案:

答案 0 :(得分:0)

简而言之,

LSP与您使用的变量和引用的可替换性有关。一个常见的示例是使用collections api:

ArrayList<String> someList = new ArrayList<>();

可以,但是假设我们有一个list方法:

public void printList(LinkedList<String> printedList) { ... }

现在,我们无法将ArrayList<String>传递给LinkedList<String>参数,因为它们是不同的类型!但是,我们所需的唯一实际功能不是LinkedListArrayList的特定功能,而是List本身的特定功能。因此,我们以可替代的方式

List<String> someList = new ArrayList<>(); //still an arraylist!

public void printList(List<String> printedList) { ... } //any list type

现在我们可以传递参数了,因为我们不必不必要地绑定到不需要其功能的子类型。

就内存级别而言,这些对象在堆内存中仍然是相同的对象,您只需将它们称为它们的超类型即可(实际上,如果知道类型,则可以对其进行下转换)。

因此,以您的示例为例,您可能会遇到一种情况,即存在的任何车辆都有颜色。所以我们有方法:

public class Vehicle {

    public Color getColor() { ... }
    public void setColor(Color color) { ... }

}

在此过程中,Vehicle any 子类将具有颜色方法,但与BMW或{{1} }。但是,这与继承比LSP更相关。

答案 1 :(得分:0)

LSP 说,当我们扩展一个类时,子类和超类之间的关系必须是 IS A 。在您的示例中,汽车 IS A 车辆。因此,当Car类扩展Vehicle时,不会违反LSP。

在内存级别中,创建了一个由Vehicle引用的Car对象。并且BMW参考将能够访问Vehicle的所有公共和受保护的方法,实例变量。