Tôi đã tự hỏi nếu có một trường hợp sử dụng hợp lệ để có thể xác định đúng các thuộc tính và chức năng nội bộ cụ thể của một lớp theo cách tương tự như cách một giao diện xác định các thuộc tính và chức năng chung của một lớp.
Hãy tưởng tượng nhiệm vụ mà bạn phải xây dựng một lớp mô tả một con người.
Rõ ràng, mỗi người là một sinh vật hình người nhưng không phải mọi sinh vật hình người đều là một con người, vì vậy bạn có thể có một giao diện IHumanoid với các chức năng như thế này (vì nó không hữu ích để mã hóa kế hoạch cơ thể vào lớp):
public interface IHumanoid {
function get head():IHead;
function get torso():ITorso;
function get leftArm():IArm;
function get rightArm():IArm;
function get leftLeg():ILeg;
function get rightLeg():ILeg;
}
Hơn nữa và rõ ràng, mỗi người là một động vật có vú nhưng không phải mọi động vật đều là một con người, vì vậy có lẽ có một giao diện khác là IMammal với hai định nghĩa cho nam và nữ trôi nổi ở đâu đó:
public interface IMammal {
function procreate(partner:IMammal):void;
}
public interface IMaleMammal extends IMammal {
function inseminate(female:IFemaleMammal):void;
}
public interface IFemaleMammal extends IMammal {
function conceive(partner:IMaleMammal):Boolean;
function giveBirth():IMammal;
function nurse(offspring:IMammal):void;
}
Vì vậy, lớp của chúng ta bây giờ có thể trông giống như thế này:
public class Human implements IHumanoid, IMammal {
private var _head:IHead;
private var _torso:ITorso;
private var _leftArm:IArm;
private var _rightArm:IArm;
private var _leftLeg:ILeg;
private var _rightLeg:ILeg;
public function Human() {
// ctor...
}
public function get head():IHead {
return _head;
}
public function get torso():ITorso {
return _torso;
}
public function get leftArm():IArm {
return _leftArm;
}
public function get rightArm():IArm {
return _rightArm;
}
public function get leftLeg():ILeg {
return _leftLeg;
}
public function get rightLeg():ILeg {
return _rightLeg;
}
public function procreate(partner:IMammal):void {
// "abstract" function
}
}
public class MaleHuman extends Human implements IMaleMammal {
override public function procreate(partner:IMammal):void {
if (partner is IFemaleMammal) {
inseminate(partner);
}
}
public function inseminate(female:IFemaleMammal):void {
female.conceive(this);
}
}
public class FemaleHuman extends Human implements IFemaleMammal {
override public function procreate(partner:IMammal):void {
if (partner is IMaleMammal) {
conceive(partner);
}
}
public function conceive(partner:IMaleMammal):Boolean {
// ...
}
public function giveBirth():IMammal {
// ...
}
public function nurse(offspring:IMammal):void {
// ...
}
}
Từ đó, chúng ta có thể triển khai các lớp của mình hơn nữa và mọi thứ đều hoạt động tốt và ổn cho đến khi chúng ta có nhiệm vụ sử dụng các giao diện hiện có để thực hiện một số lớp khác. Có lẽ là một con khỉ đột, một con orca và một con thú mỏ vịt.
Bỏ qua vấn đề lớn, thú mỏ vịt sẽ đặt ra cấu trúc giao diện hiện tại của chúng tôi (* ho * trứng đặt động vật có vú * ho *), chúng tôi có "vấn đề" là không có gì ngăn cản chúng tôi cung cấp cho não khỉ đột 2, phổi 8 orca và nửa thú mỏ vịt một tá gan. Và mặc dù chúng tôi có thể bị xử lý kỷ luật đủ để tuân theo cấu trúc động vật có vú, nhưng chúng tôi không thể đảm bảo như vậy nếu chúng tôi mở API cho các nhà phát triển khác, những người có thể mã hóa một số thứ nghiêm trọng mà vẫn trông ổn với thế giới bên ngoài.
Do đó, tôi đã tự hỏi nếu có một trường hợp sử dụng hợp lệ để tạo ra một cái gì đó giống như "giao diện riêng" xác định các chức năng và thuộc tính không công khai. Có lẽ một cái gì đó dọc theo những dòng này:
public structure SMammal {
function get brain():IBrain;
function get liver():ILiver;
function get leftLung():ILung;
function get rightLung():ILung;
function get leftKidney():IKidney;
function get rightKidney():IKidney;
}
public class Human implements IHumanoid, IMammal follows SMammal {
private function get brain():IBrain {
// ...
}
private function get liver():ILiver {
// ...
}
// etc. etc.
}
Liệu một tính năng như vậy tồn tại trong bất kỳ ngôn ngữ lập trình? Các lớp trừu tượng có thể được sử dụng để giải quyết điều này? Hoặc chúng ta không nên quan tâm đến điều này miễn là giao diện công cộng bằng cách nào đó hoạt động như mong đợi?