दिलचस्प पोस्ट
पायथन रिगेक्स मिलान वाले यूनिकोड गुण क्या आप एक्सटेंशन से क्रोम: // पृष्ठों तक पहुंच सकते हैं? एक EventTrigger के साथ एक संपत्ति की स्थापना कैसे आईओएस एसडीके में एक छाता ढांचा बनाने के लिए? हम एक जावा प्रोग्राम कंसोल आउटपुट को कई फाइलों में कैसे रीडायरेक्ट कर सकते हैं? पोस्ट के लिए अजाक्स ट्यूटोरियल और प्राप्त करें एसवीजी में उत्पत्ति परिवर्तन कैसे करें वक्रार और नवरर्चार के बीच अंतर क्या है? एक्लिप्से में यूटीएफ -8 एन्कोडिंग का समर्थन कैसे करें यूआरएल में यूनिकोड वर्ण अपने संबंधित मूल्यों के आधार पर सॉर्ट किया गया एनएसएडीआई कुंजियाँ सीएसएस स्टाइलिंग चेकबॉक्सेस फ्रैगमेंट के सेट को समझना रिटाइन इन्स्टेंस (बूलियन) गोलांग में कोड की लंबी लाइन को कैसे तोड़ा जाए? WPF MVVM ट्रीदृश्य चयनित आईटम

सी # में एकाधिक वंशानुक्रम

चूंकि बहुत से विरासत खराब है (यह स्रोत को और अधिक जटिल बना देता है) सी # ऐसे पैटर्न को सीधे नहीं प्रदान करता है लेकिन कभी-कभी यह क्षमता प्राप्त करने में सहायक होगा।

उदाहरण के लिए मैं इंटरफेस और तीन वर्गों की तरह गुम एकाधिक विरासत पैटर्न को लागू करने में सक्षम हूं:

public interface IFirst { void FirstMethod(); } public interface ISecond { void SecondMethod(); } public class First:IFirst { public void FirstMethod() { Console.WriteLine("First"); } } public class Second:ISecond { public void SecondMethod() { Console.WriteLine("Second"); } } public class FirstAndSecond: IFirst, ISecond { First first = new First(); Second second = new Second(); public void FirstMethod() { first.FirstMethod(); } public void SecondMethod() { second.SecondMethod(); } } 

जब भी मैं इंटरफेस में से किसी एक को एक विधि जोड़ता हूं, मुझे कक्षा फर्स्ट एंडसेकंड को भी बदलना होगा

क्या कई मौजूदा वर्गों को एक नए वर्ग में इंजेक्ट करने का एक तरीका है, जैसे कि सी ++ में संभव है?

हो सकता है कि किसी प्रकार की कोड पीढ़ी का उपयोग कर एक समाधान हो?

या यह इस तरह दिख सकता है (काल्पनिक सी # सिंटैक्स):

 public class FirstAndSecond: IFirst from First, ISecond from Second { } 

इसलिए कि जब मैं इंटरफेस में से किसी एक को संशोधित करता हूं, तब प्रथम और दूसरे वर्ग को अपडेट करने की आवश्यकता नहीं होगी।


संपादित करें

शायद यह एक व्यावहारिक उदाहरण पर विचार करना बेहतर होगा:

आपके पास एक मौजूदा क्लास (उदाहरण के लिए एक पाठ आधारित टीसीपी क्लाइंट आईटेक्स्ट टीसीपीक्लाइंट पर आधारित है) जो आप पहले से ही अपने प्रोजेक्ट के अंदर विभिन्न स्थानों पर उपयोग करते हैं। अब आपको अपने वर्ग के एक घटक बनाने की आवश्यकता महसूस होती है, जो कि विंडोज़ रूपों डेवलपर्स के लिए आसानी से सुलभ हो।

जहाँ तक मुझे पता है कि आपके पास वर्तमान में ऐसा करने के दो तरीके हैं:

  1. एक नया वर्ग लिखें जो कि घटकों से विरासत में मिला है और TextTcpClient क्लास के इंटरफ़ेस का उपयोग करके क्लास के एक उदाहरण का प्रयोग करते हैं जैसा कि फर्स्ट एंडसेकंड के साथ दिखाया गया है।

  2. एक नई कक्षा लिखें जो TextTcpClient से विरासत में मिली है और किसी भी तरह IComponent लागू करता है (वास्तव में अभी तक यह नहीं की कोशिश की है)

दोनों ही मामलों में आपको प्रति विधि काम करना चाहिए और प्रति वर्ग में नहीं। चूंकि आप जानते हैं कि हमें TextTcpClient और Component के सभी तरीकों की आवश्यकता होगी, यह उन दोनों में से एक क्लास को संयोजित करने का सबसे आसान समाधान होगा।

संघर्ष से बचने के लिए यह कोड पीढ़ी द्वारा किया जा सकता है, जहां परिणाम बाद में बदला जा सकता है, लेकिन यह हाथ से टाइप करना गधा में एक शुद्ध दर्द है

वेब के समाधान से एकत्रित समाधान "सी # में एकाधिक वंशानुक्रम"

चूंकि बहुत से विरासत खराब है (यह स्रोत को और अधिक जटिल बना देता है) सी # ऐसे पैटर्न को सीधे नहीं प्रदान करता है लेकिन कभी-कभी यह क्षमता प्राप्त करने में सहायक होगा।

सी # और शुद्ध सीएलआर ने एमआई नहीं लागू किया है क्योंकि उन्होंने यह निष्कर्ष नहीं निकाला है कि यह सी #, वीबीनेट और अन्य भाषाओं के बीच अभी तक कैसे काम करेगा, नहीं, क्योंकि "यह स्रोत अधिक जटिल बना देगा"

एमआई एक उपयोगी अवधारणा है, संयुक्त राष्ट्र के उत्तर वाले सवाल हैं: – "जब आपके पास विभिन्न सुपर क्लासेस में एक से अधिक सामान्य आधार वर्ग हैं, तो आप क्या करते हैं?

पर्ल एकमात्र भाषा है जिसकी मैंने कभी काम किया है जहां एमआई काम करता है और अच्छी तरह से काम करता है नेट एक दिन इसे शुरू कर सकता है लेकिन अभी तक नहीं, सीएलआर पहले से ही एमआई का समर्थन करता है, लेकिन जैसा कि मैंने कहा है, इसके लिए अभी तक इसके लिए कोई भाषा निर्माण नहीं है।

तब तक आप प्रॉक्सी ऑब्जेक्ट्स और इसके बजाय कई इंटरफेस के साथ फंस गए हैं 🙁

कई वंशानुक्रमों को अनुकरण करने की कोशिश करने के बजाय संरचना का उपयोग करने पर विचार करें। आप किस वर्ग को रचना बनाते हैं, यह परिभाषित करने के लिए इंटरफेस का उपयोग कर सकते हैं, उदाहरण के लिए: ISteerable का अर्थ है SteeringWheel प्रकार की संपत्ति, IBrakable का मतलब है कि BrakePedal प्रकार की संपत्ति है।

एक बार जब आप ऐसा करते हैं, तो आप उन निहित गुणों पर कॉलिंग विधियों को सरल बनाने के लिए सी # 3.0 में एक्स्टेंशन मेथड्स फीचर को जोड़ सकते हैं, उदाहरण के लिए:

 public interface ISteerable { SteeringWheel wheel { get; set; } } public interface IBrakable { BrakePedal brake { get; set; } } public class Vehicle : ISteerable, IBrakable { public SteeringWheel wheel { get; set; } public BrakePedal brake { get; set; } public Vehicle() { wheel = new SteeringWheel(); brake = new BrakePedal(); } } public static class SteeringExtensions { public static void SteerLeft(this ISteerable vehicle) { vehicle.wheel.SteerLeft(); } } public static class BrakeExtensions { public static void Stop(this IBrakable vehicle) { vehicle.brake.ApplyUntilStop(); } } public class Main { Vehicle myCar = new Vehicle(); public void main() { myCar.SteerLeft(); myCar.Stop(); } } 

मुझे यह भी पसंद है – यह है कि मैं व्यक्तिगत रूप से एक मिश्रण के रूप में संदर्भित हूं, हालांकि मुझे पता है कि यह अतिभारित शब्द है मैं विशिष्ट तरीकों के लिए अपना स्वयं का कार्यान्वयन प्रदान करने के विकल्प के साथ, अंतरफलक को लागू करने के लिए उपयोग किए जाने वाले चर को निर्दिष्ट करने में सक्षम होना चाहता हूं।

मैंने इसके बारे में अधिक विस्तार से ब्लॉग किया है – हालांकि, विरासत के संदर्भ में इसका अर्थ क्या हो सकता है, इस बारे में एक जानबूझकर अतिरेक के संदर्भ में।

मुझे कोई कारण नहीं है कि यह सी # संकलक में लागू नहीं किया जा सकता है – लेकिन यह भाषा जटिलता का एक और हिस्सा है …

मैंने एक सी # पोस्ट-कंपाइलर बनाया है जो इस प्रकार की चीज़ को सक्षम करता है:

 using NRoles; public interface IFirst { void FirstMethod(); } public interface ISecond { void SecondMethod(); } public class RFirst : IFirst, Role { public void FirstMethod() { Console.WriteLine("First"); } } public class RSecond : ISecond, Role { public void SecondMethod() { Console.WriteLine("Second"); } } public class FirstAndSecond : Does<RFirst>, Does<RSecond> { } 

आप पोस्ट-कंपाइलर को विज़ुअल स्टूडियो पोस्ट-बिल्ड-इवेंट के रूप में चला सकते हैं:

सी: \ some_path \ nroles-v0.1.0-bin \ nutate.exe "$ (लक्ष्यपथ)"

उसी विधानसभा में आप इसे इस तरह प्रयोग करते हैं:

 var fas = new FirstAndSecond(); fas.As<RFirst>().FirstMethod(); fas.As<RSecond>().SecondMethod(); 

दूसरे विधानसभा में आप इसे इस तरह प्रयोग करते हैं:

 var fas = new FirstAndSecond(); fas.FirstMethod(); fas.SecondMethod(); 

आपके पास एक सार बेस क्लास हो सकता है जो IFirst और इसाकेंड दोनों का कार्यान्वयन करता है, और फिर उस आधार से प्राप्त होता है।

एमआई कोई बुरा नहीं है, जो सभी (गंभीरता से) इस्तेमाल किया है इसे प्यार करता है और यह नहीं करता है कोड जटिल! कम से कम अन्य निर्माणों की तुलना में कोड जटिल हो सकता है। बुरा कोड खराब कोड है चाहे चाहे एमआई चित्र में है या नहीं।

वैसे भी, मुझे एक से अधिक वंशानुक्रम के लिए एक अच्छा सा समाधान मिल गया है जो मैं साझा करना चाहता था, यह है; http://ra-ajax.org/lsp-liskov-substitution-principle-to-be-or-not-to-be.blog या आप मेरे हस्ताक्षर में लिंक का अनुसरण कर सकते हैं … 🙂

यदि आप प्रतिबंध के साथ रह सकते हैं कि IFirst और ISecond के तरीकों को केवल IFirst और इसाकंड (जैसे आपके उदाहरण में) के अनुबंध के साथ ही बातचीत करना चाहिए … आप विस्तार पद्धतियों के साथ आप क्या पूछ सकते हैं। व्यवहार में, यह शायद ही मामला है।

 public interface IFirst {} public interface ISecond {} public class FirstAndSecond : IFirst, ISecond { } public static MultipleInheritenceExtensions { public static void First(this IFirst theFirst) { Console.WriteLine("First"); } public static void Second(this ISecond theSecond) { Console.WriteLine("Second"); } } 

///

 public void Test() { FirstAndSecond fas = new FirstAndSecond(); fas.First(); fas.Second(); } 

तो मूल विचार यह है कि आप इंटरफेस में आवश्यक कार्यान्वयन को परिभाषित करते हैं … इस आवश्यक सामग्री को विस्तार विधियों में लचीला कार्यान्वयन का समर्थन करना चाहिए। किसी भी समय आपको एक एक्सटेंशन विधि जोड़ने के बजाय "इंटरफ़ेस में तरीकों को जोड़ने" की आवश्यकता है

हाँ इंटरफ़ेस का उपयोग करना परेशानी है क्योंकि कभी भी हम क्लास में एक विधि जोड़ते हैं जिससे हमें अंतरफलक में हस्ताक्षर जोड़ना पड़ता है। साथ ही, अगर हमारे पास पहले से ही कोई ऐसा तरीका है जिसमें कोई गुच्छा है लेकिन इसके लिए कोई अंतरफलक नहीं है? हमें उन सभी वर्गों के लिए मैन्युअल रूप से इंटरफ़ेस बनाना होगा जो हम से प्राप्त करना चाहते हैं। और सबसे बुरी बात यह है कि अगर बच्चे को इंटरफ़ेस में सभी इंटरफ़ेस को कई इंटरफ़ेस से प्राप्त करना है, तो हमें सभी तरीकों को लागू करना होगा।

मुखौटा डिजाइन पैटर्न का अनुसरण करके हम एक्सेसर्स का उपयोग करते हुए एकाधिक वर्गों से इनहेरिटिंग का अनुकरण कर सकते हैं। वर्गों को प्राप्त करने के लिए कक्षाओं के भीतर संपत्तियों के रूप में घोषित करें और उन सभी गुणों और गुणों को उस कक्षा से प्राप्त करें, और मूल कक्षा के निर्माता में माता-पिता वर्गों का तत्त्व।

उदाहरण के लिए:

  namespace OOP { class Program { static void Main(string[] args) { Child somechild = new Child(); somechild.DoHomeWork(); somechild.CheckingAround(); Console.ReadLine(); } } public class Father { public Father() { } public void Work() { Console.WriteLine("working..."); } public void Moonlight() { Console.WriteLine("moonlighting..."); } } public class Mother { public Mother() { } public void Cook() { Console.WriteLine("cooking..."); } public void Clean() { Console.WriteLine("cleaning..."); } } public class Child { public Father MyFather { get; set; } public Mother MyMother { get; set; } public Child() { MyFather = new Father(); MyMother = new Mother(); } public void GoToSchool() { Console.WriteLine("go to school..."); } public void DoHomeWork() { Console.WriteLine("doing homework..."); } public void CheckingAround() { MyFather.Work(); MyMother.Cook(); } } } 

इस संरचना वर्ग के साथ बच्चे को कक्षा पिता और माता के सभी तरीकों और गुणों तक पहुंच प्राप्त होगी, जो कई विरासत का अनुकरण करते हैं, माता-पिता कक्षाओं के एक उदाहरण का उत्तराधिकारी हैं। बिल्कुल नहीं, लेकिन यह व्यावहारिक है।

मल्टीपल इनहेरिटमेंट उन चीजों में से एक है, जो आमतौर पर समस्याओं की तुलना में अधिक समस्याओं का कारण बनती है। सी ++ में आप अपने आप को लटका देने के लिए पर्याप्त रस्सी के पैटर्न को फिट करते हैं, लेकिन जावा और सी # ने आपको विकल्प नहीं देने का सुरक्षित मार्ग जाने के लिए चुना है। सबसे बड़ी समस्या यह है कि यदि आप एक से अधिक वर्गों का उत्तराधिकार प्राप्त करते हैं जो एक ही हस्ताक्षर के साथ एक विधि है जो कि विरासत को लागू नहीं करता है किस वर्ग की विधि को चुनना चाहिए? या यह संकलन नहीं करना चाहिए? आम तौर पर ज्यादातर चीजों को लागू करने का एक और तरीका है जो एकाधिक विरासत पर भरोसा नहीं करता है।

यदि एक्स वाई से निकलता है, तो उसके पास दो कुछ ओर्थोगोनल प्रभाव होते हैं:

  1. वाई एक्स के लिए डिफ़ॉल्ट कार्यक्षमता प्रदान करेगा, इसलिए एक्स के लिए कोड को केवल वाई से अलग करना होगा।
  2. लगभग कहीं भी एक Y उम्मीद की जाएगी, एक एक्स बजाय इस्तेमाल किया जा सकता है

यद्यपि विरासत दोनों सुविधाओं के लिए प्रदान करती है, हालाँकि ऐसी परिस्थितियों की कल्पना करना मुश्किल नहीं होता है जहां दूसरे के बिना उपयोग किया जा सकता है कोई नई भाषा नहीं है जो मुझे पता है कि दूसरे के बिना पहली को लागू करने का एक सीधा तरीका है, हालांकि कोई ऐसे आधार वर्ग को परिभाषित करके ऐसी कार्यक्षमता प्राप्त कर सकता है जो कभी भी सीधे उपयोग नहीं किया जाता है, और एक या अधिक कक्षाएं जो बिना कुछ भी जोड़ते हैं नया (ऐसी कक्षाएं अपने सभी कोड को साझा कर सकती हैं, लेकिन एक दूसरे के लिए प्रतिस्थापन नहीं होगी)। हालांकि, किसी भी सीएलआर-अनुपालन की भाषा, इंटरफेस के उपयोग की अनुमति देती है जो पहले (सदस्य पुन: उपयोग) के बिना इंटरफेस (प्रतिस्थापन क्षमता) की दूसरी सुविधा प्रदान करती है।

मुझे पता है कि मुझे पता है कि इसकी अनुमति नहीं है और इतने पर, कुछ समय वास्तव में उन लोगों के लिए इसकी आवश्यकता है:

 class a {} class b : a {} class c : b {} 

जैसे मेरे मामले में मैं इस वर्ग को करना चाहता था b: प्रपत्र (हां, windows.forms) वर्ग c: b {}

कारण समारोह के आधा समान थे और इंटरफ़ेस के साथ आप उन्हें सभी को फिर से लिखना चाहिए

चूंकि एकाधिक विरासत (एमआई) का सवाल समय-समय पर फ़ैसला होता है, इसलिए मैं एक दृष्टिकोण जोड़ना चाहता हूं जो रचना पैटर्न के साथ कुछ समस्याएं बताता है।

मैं IFirst , ISecond , First , Second , First और Second दृष्टिकोण पर निर्माण, जैसा कि प्रश्न में प्रस्तुत किया गया था। मैं IFirst को नमूना कोड को कम करता IFirst , क्योंकि पैटर्न इंटरफेस / एमआई बेस क्लास की संख्या पर ध्यान दिए बिना समान रहता है।

मान लीजिए, एमआई First और Second साथ ही बेस क्लास से केवल सार्वजनिक इंटरफ़ेस तत्वों का उपयोग करते हुए, एक ही बेस क्लास BaseClass से प्राप्त होता है

यह First और Second कार्यान्वयन में BaseClass लिए एक कंटेनर संदर्भ जोड़कर व्यक्त किया जा सकता है:

 class First : IFirst { private BaseClass ContainerInstance; First(BaseClass container) { ContainerInstance = container; } public void FirstMethod() { Console.WriteLine("First"); ContainerInstance.DoStuff(); } } ... 

चीजें अधिक जटिल हो जाती हैं, जब BaseClass क्लास से संरक्षित इंटरफ़ेस तत्व संदर्भित होते हैं या जब एमआई में First और Second कक्षाएं होती हैं, तो उनके उपवर्गों को कुछ अमूर्त भागों को लागू करने की आवश्यकता होती है।

 class BaseClass { protected void DoStuff(); } abstract class First : IFirst { public void FirstMethod() { DoStuff(); DoSubClassStuff(); } protected abstract void DoStuff(); // base class reference in MI protected abstract void DoSubClassStuff(); // sub class responsibility } 

सी # नेस्टेड कक्षाओं को अपने युक्त वर्गों के संरक्षित / निजी तत्वों तक पहुंचने की अनुमति देता है, इसलिए इसका उपयोग First कार्यान्वयन से सार बिट्स को लिंक करने के लिए किया जा सकता है।

 class FirstAndSecond : BaseClass, IFirst, ISecond { // link interface private class PartFirst : First { private FirstAndSecond ContainerInstance; public PartFirst(FirstAndSecond container) { ContainerInstance = container; } // forwarded references to emulate access as it would be with MI protected override void DoStuff() { ContainerInstance.DoStuff(); } protected override void DoSubClassStuff() { ContainerInstance.DoSubClassStuff(); } } private IFirst partFirstInstance; // composition object public FirstMethod() { partFirstInstance.FirstMethod(); } // forwarded implementation public FirstAndSecond() { partFirstInstance = new PartFirst(this); // composition in constructor } // same stuff for Second //... // implementation of DoSubClassStuff private void DoSubClassStuff() { Console.WriteLine("Private method accessed"); } } 

इसमें कुछ बॉयलरप्लेट शामिल है, लेकिन अगर पहले विधि और दूसरा विधि का वास्तविक कार्यान्वयन पर्याप्त रूप से जटिल है और एक्सेस किए गए निजी / संरक्षित तरीकों की मात्रा मध्यम है, तो यह पैटर्न कई वंशानुक्रमों की कमी को दूर करने में मदद कर सकता है।

यह लॉरेंस वेनहम के उत्तर की तर्ज पर है, लेकिन आपके उपयोग के मामले पर निर्भर करता है, यह सुधार या नहीं हो सकता है – आपको सेटर्स की आवश्यकता नहीं है

 public interface IPerson { int GetAge(); string GetName(); } public interface IGetPerson { IPerson GetPerson(); } public static class IGetPersonAdditions { public static int GetAgeViaPerson(this IGetPerson getPerson) { // I prefer to have the "ViaPerson" in the name in case the object has another Age property. IPerson person = getPerson.GetPersion(); return person.GetAge(); } public static string GetNameViaPerson(this IGetPerson getPerson) { return getPerson.GetPerson().GetName(); } } public class Person: IPerson, IGetPerson { private int Age {get;set;} private string Name {get;set;} public IPerson GetPerson() { return this; } public int GetAge() { return Age; } public string GetName() { return Name; } } 

अब कोई भी वस्तु जो जानता है कि एक व्यक्ति IGetPerson को कैसे लागू कर सकता है, और यह स्वतः GetAgeViaPerson () और GetNameViaPerson () विधियां प्राप्त कर लेगा। इस बिंदु से, मूल रूप से सभी व्यक्ति कोड IGetPerson में जाता है, नए आईवर के अलावा आईपर्सन में नहीं, जो दोनों में जाना पड़ता है। और इस तरह के कोड का उपयोग करने में, आपको चिंतित होने की ज़रूरत नहीं है कि आपकी आईजीटीपर्सिंग ऑब्जेक्ट वास्तव में एक आईपर्सन है या नहीं।

एकाधिक विरासत सी # में इंटरफेस का उपयोग करके प्राप्त किया जा सकता है। इसे एक उदाहरण की सहायता से समझाया जा सकता है –

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MultipleInheritApplication { interface calc1 { int add(int a, int b); } interface calc2 { int sub(int x, int y); } interface calc3 { int mul(int r, int s); } interface calc4 { int div(int c, int d); } class Calculation : calc1, calc2, calc3, calc4 { public int result1; public int add(int a, int b) { return result1 = a + b; } public int result2; public int sub(int x, int y) { return result2 = x - y; } public int result3; public int mul(int r, int s) { return result3 = r * s; } public int result4; public int div(int c, int d) { return result4 = c / d; } class Program { static void Main(string[] args) { Calculation c = new Calculation(); c.add(8, 2); c.sub(20, 10); c.mul(5, 2); c.div(20, 10); Console.WriteLine("Multiple Inheritance concept Using Interfaces :\n "); Console.WriteLine("Addition: " + c.result1); Console.WriteLine("Substraction: " + c.result2); Console.WriteLine("Multiplication :" + c.result3); Console.WriteLine("Division: " + c.result4); Console.ReadKey(); } } } } 

हम सभी इस के साथ इंटरफ़ेस पथ नीचे जा रहे हैं, लेकिन स्पष्ट दूसरी संभावना, यह करने के लिए क्या करना है OOP क्या करना है, और अपने विरासत वृक्ष का निर्माण … (यह नहीं है जो वर्ग डिजाइन सभी है के बारे में?)

 class Program { static void Main(string[] args) { human me = new human(); me.legs = 2; me.lfType = "Human"; me.name = "Paul"; Console.WriteLine(me.name); } } public abstract class lifeform { public string lfType { get; set; } } public abstract class mammal : lifeform { public int legs { get; set; } } public class human : mammal { public string name { get; set; } } 

यह संरचना कोड के पुन: प्रयोज्य ब्लॉक प्रदान करता है और, निश्चित रूप से, ओओपी कोड कैसे लिखा जाना चाहिए?

यदि यह विशेष दृष्टिकोण बिल को काफी फिट नहीं करता है तो हम आवश्यक वस्तुओं पर आधारित नई कक्षाएं बनाते हैं …

 class Program { static void Main(string[] args) { fish shark = new fish(); shark.size = "large"; shark.lfType = "Fish"; shark.name = "Jaws"; Console.WriteLine(shark.name); human me = new human(); me.legs = 2; me.lfType = "Human"; me.name = "Paul"; Console.WriteLine(me.name); } } public abstract class lifeform { public string lfType { get; set; } } public abstract class mammal : lifeform { public int legs { get; set; } } public class human : mammal { public string name { get; set; } } public class aquatic : lifeform { public string size { get; set; } } public class fish : aquatic { public string name { get; set; } }