精华内容
下载资源
问答
  • 小编典典当然,下面是“观察者”模式的具体示例,该模式在记录器系统中使用类和接口来实现多态行为:interface ILogger{public void handleEvent (String event);}class FileLogger implements ILogger{public void ...

    小编典典

    当然,

    下面是“观察者”模式的具体示例,该模式在记录器系统中使用类和接口来实现多态行为:

    interface ILogger{

    public void handleEvent (String event);

    }

    class FileLogger implements ILogger{

    public void handleEvent (String event){

    //write to file

    }

    }

    class ConsoleLogger implements ILogger{

    public void handleEvent (String event){

    System.out.println( event );

    }

    }

    class Log {

    public void registerLogger (ILogger logger){

    listeners.add(logger);

    }

    public void log (String event){

    foreach (ILogger logger in listeners){

    logger.handleEvent(event); //pass the log string to both ConsoleLogger and FileLogger!

    }

    }

    private ArrayList listeners;

    }

    然后,您可以按以下方式使用它:

    public static void main(String [] args){

    Log myLog();

    FileLogger myFile();

    ConsoleLogger myConsole();

    myLog.registerLogger( myFile );

    myLog.registerLogger( myConsole );

    myLog.log("Hello World!!");

    myLog.log("Second log event!");

    }

    希望这有助于您理解接口和多态性。

    2020-09-24

    展开全文
  • C#多态的三种实现方式

    千次阅读 2021-02-16 10:18:22
    C#实现多态主要有3种方法,虚方法,抽象类,接口 1 虚方法 ​ 在父类的方法前面加关键字virtual, 子类重写该方法时在方法名前面加上override关键字,例如下面的Person类的SayHello方法 class Person { public ...

    C#实现多态主要有3种方法,虚方法,抽象类,接口

    1 虚方法

    ​ 在父类的方法前面加关键字virtual, 子类重写该方法时在方法名前面加上override关键字,例如下面的Person类的SayHello方法

    class Person
    {
        public Person(string name)
        {
            this.Name = name;
        }
    
        string _name;
    
        public string Name { get => _name; set => _name = value; }
    
        //父类方法加virtual,子类用override重写该方法,就实现了多态 
        public virtual void SayHello()   
        {
            Console.WriteLine("我是父类的方法");
        }
    }
    

    ​ 学生类和教师都继承于Person

    class Student : Person
    {
        public Student(string name) : base(name) { }
    
        public override void SayHello()
        {
            Console.WriteLine("我叫{0}, 我是学生", this.Name);
        }
    }
    
    class Teacher:Person
    {
        public Teacher(string name) : base(name) { }
    
        public override void SayHello()
        {
            Console.WriteLine("我叫{0}, 我是老师", this.Name);
        }
    }
    

    然后在Main函数中使用多态

    Student st = new Student("李雷");
    Teacher th = new Teacher("井边君");
    
    Person[] p = { st, th };  //子类对象赋给父类
    
    for(int i = 0; i < p.Length; i++)
    {
        p[i].SayHello();
    }
    
    Console.ReadKey();
    

    本例全部代码

    using System;
    
    namespace 多态之虚方法
    {
        class Program
        {
            static void Main(string[] args)
            {
                Student st = new Student("李雷");
                Teacher th = new Teacher("井边君");
    
                Person[] p = { st, th };  //子类对象赋给父类
    
                for(int i = 0; i < p.Length; i++)
                {
                    p[i].SayHello();
                }
    
                Console.ReadKey();
            }
        }
    
        class Person
        {
            public Person(string name)
            {
                this.Name = name;
            }
    
            string _name;
    
            public string Name { get => _name; set => _name = value; }
    
            //父类方法加virtual,子类用override重写该方法,就实现了多态 
            public virtual void SayHello()   
            {
                Console.WriteLine("我是父类的方法");
            }
        }
    
        class Student : Person
        {
            public Student(string name) : base(name) { }
    
            public override void SayHello()
            {
                Console.WriteLine("我叫{0}, 我是学生", this.Name);
            }
        }
    
        class Teacher:Person
        {
            public Teacher(string name) : base(name) { }
    
            public override void SayHello()
            {
                Console.WriteLine("我叫{0}, 我是老师", this.Name);
            }
        }
    }
    

    2 抽象类

    在类前面加关键字abstract,方法前面加abstract,抽象方法不能有函数体。

    抽象类的特点:

    (1)可以有字段

    (2)可以有非抽象方法

    抽象类实现多态的代码如下

    using System;
    using System.Collections.Generic;
    
    namespace 多态之抽象类
    {
        abstract class Person
        {
            //抽象方法不能有函数体
            public abstract void SayHello();
        }
    
        class Student : Person
        {
            public override void SayHello()
            {
                Console.WriteLine("我是子类Student重写的抽象方法"); ;
            }
        }
    
        class Teacher : Person
        {
            public override void SayHello()
            {
                Console.WriteLine("我是子类Teacher重写的抽象方法"); ;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                List<Person> clist = new List<Person>();
    
                Student st = new Student();
                Teacher th = new Teacher();
                clist.Add(st);
                clist.Add(th);
    
                foreach(Person p in clist)
                {
                    p.SayHello();
                }
    
                Console.ReadKey();
            }
        }
    }
    

    3 接口实现多态

    代码如下

    using System;
    using System.Collections.Generic;
    
    namespace 多态之接口
    {
        public interface IWeapon
        {
            void Fire();
        }
    
        class Gun : IWeapon
        {
            public void Fire()
            {
                Console.WriteLine("我是枪");
            }
        }
    
        class Sword : IWeapon
        {
            public void Fire()
            {
                Console.WriteLine("我是剑");
            }
    
        }
    
        class Tank : IWeapon
        {
            public void Fire()
            {
                Console.WriteLine("我是坦克");
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                List<IWeapon> list = new List<IWeapon>();
    
                Gun gun = new Gun();
                Sword sw = new Sword();
                Tank ta = new Tank();
                list.Add(gun);
                list.Add(sw);
                list.Add(ta);
    
                foreach (IWeapon p in list)
                {
                    p.Fire();
                }
    
                Console.ReadKey();
            }
        }
    }
    

    接口的特点

    (1)接口里的方法不能有修饰符,默认是public

    (2)接口的方法不能有函数体

    (3)接口中不能包含示例字段,不能有构造函数

    (4)接口里的方法被继承的类重写时,不需要用override关键字,接口不能被实例化

    (5)接口之间可以继承,并且可以多继承;接口不能继承于类,但是类可以继承于接口

    (6)一个类可以同时继承一个类,并实现多个接口

    展开全文
  • 学习java刚刚入门的小伙伴们,不知道大家在初次接触java中的多态一概念的时候,是否能清晰的讲出实现多态的机制是什么吗?什么才是java中的多态呢?多态性是指的面向对象程序设计代码重用的一个重要的机制,对于Java多...

    学习java刚刚入门的小伙伴们,不知道大家在初次接触java中的多态一概念的时候,是否能清晰的讲出实现多态的机制是什么吗?什么才是java中的多态呢?

    多态性是指的面向对象程序设计代码重用的一个重要的机制,对于Java多态性,应该都不是第一次才听到的。

    很大一部分的java程序员会把多态看作对象的一种能力,使其能调用正确的一个方法版本。

    虽然说是这样的,可是这种面向实现的观点导致了多态的神奇功能,胜于仅仅把多态看成纯粹的概念的。

    重载的多态:

    重载就是允许用相同的运算符或方法,去表示截然不同的意义。‘+’在Javaa的程序中有两个意思:一是两个double型的数相加;二是两个字符串相连。另外还有整型相加,长整型...。

    这些运算符的重载,是依赖于编译器根据上下文做出的选择的。

    以往的编译器就会把操作数隐式转换为完全符合操作符的类型。虽然说Java明确的支持重载,但还是不支持用户定义的操作符重载的。

    Java是支持用户定义的函数重载的。一个类中是可以有相同名字的方法的,这些方法也是可以有不同的意义的。

    这些重载的方法当中,必须要满足参数数目的不同,相同位置上的参数类型也不同。这些不同就可以帮助编译器区分不同版本的方法了。

    参数的多态:

    参数多态是允许把许多类型抽象成单一的表示的。比如说,List抽象类中,描述了一组具有同样特征的对象,提供了一个通用的模板。

    你是可以通过指定一种类型以重用这个抽象类的。

    包含的多态:

    包含多态是通过值的类型和集合的包含关系实现了多态的行为的。在包括Java在内的众多面向对象语言里面,包含关系是子类型的。因此,Java的包含多态是子类型的多态。

    好了,以上就是本篇文章的所有内容了,还想了解多个java入门知识,记得马上关注本站信息哦,更多精彩内容等你来解锁!

    推荐阅读:

    展开全文
  • 多态实现原理

    2021-05-14 09:37:07
    (不过这里为啥多了一个我还没弄清楚,不过的确看到,三个函数地址后还有好几个数据,并且以nullptr结尾) 因此,多态实现原理就是通过virtual声明存在多态,之后生成虚表指针,管理虚函数。派生类通过重写基类的...

    多态的概念

    顾名思义,多态即多种形态。

    定义:不同继承关系的类对象,调用同一函数,产生不同行为的现象就是多态。

    我理解的多态,就是一种现象。

    这个现象即,当不同的对象执行同一个行为时,产生的结果不一样

    举个在西安乘坐公交车车费的例子:

    付费方式票价
    现金2元
    支付宝/微信扫码1元
    普通卡1元
    学生卡0.6元
    老年卡0元

    这就属于生活中的多态,都是付车费,不同身份/不同支付方式,应该支付的车费是不一样的。

    多态的构成条件

    在继承中要构成多态要满足以下条件:

    1.不同继承关系的类对象调用同一函数
    2.必须通过基类的指针或者引用调用虚函数
    3.被调用的函数必须是虚函数,并且派生类对基类的虚函数进行了重写

    虚函数

    virtual修饰的类成员函数,再次强调一定是类成员函数

    例:

    class Person{
    public:
    	virtual void ByBus(){ cout<<"票价:2元"<<endl; }
    };
    

    虚函数的重写(覆盖)

    派生类中有一个成员函数与基类的一个虚函数三个东西相同:

    1.返回值类型相同
    2.函数名字相同
    3.参数列表完全相同

    这种行为称派生类的虚函数重写了基类的虚函数

    例:

    class Person{
    public:
    	virtual void ByBus(){ cout<<"票价:2元"<<endl; }
    };
    
    class Student: public Person{
    public:
    	virtual void ByBus(){ cout<<"票价:0.6元"<<endl; }
    };
    
    class Elder: public Person{
    public:
    	virtual void ByBus(){ cout<<"票价:0元"<<endl;  }
    };
    

    虽然派生类在对基类的虚函数进行重写时,不加virtual修饰成员函数,仍可完成重写工作,效果不受影响

    但这种写法不建议,坚持良好的编程风格与代码的易读性有益于与他人合作。

    多态的原理

    首先来看一张图片
    在这里插入图片描述

    虚函数表指针及虚函数表

    当我们实例化一个Base类对象时,该对象的成员中不仅有我们定义的私有成员_b,还出现了一个根本不是我们定义的__vfptr成员。

    更令人疑惑的是,你想看看这个成员什么情况,刚敲下b.__vfptr,编译器就会给你错误警示!说这个Base里没有__vfptr成员!

    这是怎么回事?
    在这里插入图片描述
    原来,这个__vfptr就是实现多态的核心机制之一!
    __vfptr的出现是因为virtual的出现,
    如果去掉virtual,则__vfptr则会消失。

    在这里插入图片描述
    因此我们可以得出结论,一旦类中出现virtual修饰的成员函数,那么该类实例化后的对象必然有一个我们不能访问的成员__vfptr

    __vfptr叫作虚函数表指针,这个指针指向一个表,这个表里存储着对象的虚函数地址

    简单的程序展示一下:
    在这里插入图片描述
    上图中的类中有4个虚函数,因此__vfptr指向的表里存储着4个函数指针,分别指向虚函数

    Base::Func1()
    Base::Test()
    Base::Print()
    Base::Show()
    

    对象b的内存结构如下图所示:
    在这里插入图片描述
    上图中的红色表格就是虚函数表,这个表里存储所有对象b的虚函数地址,最后一个元素为nullptr作为表结束的标志。

    派生类的虚函数表

    以下面这份简单代码为例,讲讲派生类虚函数指针与基类虚函数指针的差别

    #include <iostream>
    using namespace std;
    class Base {
    public:
    	virtual void Func1() { cout << "Base::Func1()" << endl; }
    	virtual void Test() { cout << "Base::Test()" << endl; }
    	virtual void Print() { cout << "Base::Print()" << endl; }
    private:
    	int _b = 1;
    };
    class D :public Base{
    public:
    	virtual void Func1() { cout << "D::Func1()" << endl; }
    	virtual void Print() { cout << "D::Print()" << endl; }
    private:
    	int _c = 1;
    };
    int main() {
    	Base b;
    	D p;
    	return 0;
    }
    

    运行后,监视变量区如下图:
    在这里插入图片描述
    我们可以看到,基类对象b的虚函数表里面有三个函数指针,指向

    Base::Func1()
    Base::Test()
    Base::Print()
    

    而派生类对象虚函数表也有三个虚函数指针,指向

    D::Func1()
    Base::Test()
    D::Print()
    

    对比即可发现,基类中只要被派生类重写的虚函数,在虚函数表里其地址全被派生类的虚函数覆盖了!

    好一招狸猫换太子!竟然把基类的虚函数偷偷换成自己的虚函数。那这么做有什么用呢?

    请看下图:
    在这里插入图片描述
    我们定义了一个基类指针pt1,令其指向派生类对象,然后利用这指针调用方法,可以发现,基类指针调用的方法有的竟然是派生类的方法!这是怎么回事?基类对派生类的引用也发生了这种现象。仔细观察下图:
    在这里插入图片描述
    可以发现,就是因为基类指针指向的派生类对象中的虚函数表发生了变化,本应是基类的函数指针被换成了派生类的函数指针,当发生方法调用时,自然而然,指针pt1与引用p2会调用被重写的虚函数。

    当我们给派生类中增加一个基类并没有的虚函数后,因为pt1p2都是派生类对象强转过来的变量,我想调用派生类的方法没有问题吧?

    因为Base* pt1 = new D;本来就是生成了一个派生类对象,然后把这个对象地址强转成为了基类指针,这个对象必然是有MyOwn()方法的。我想通过这个指针调用MyOwn(),我觉得不过分。

    可是当我们敲下代码时,杯具了!编译器说,这玩意儿没有MyOwn()方法!怎么回事?我看派生类对象p分明可以调用MyOwn()啊!这是怎么回事?

    在这里插入图片描述
    请看下图:
    在这里插入图片描述

    其实派生类对象内存模型里该有的都有,只是当我们用基类指针去指向它时,这对象的地址会发生强制类型转换,使得基类指针只能看见基类才有的东西(红色方框)。因此pt1调用不了MyOwn()方法,但实质上是有,只是pt1看不到,访问不了而已。

    如何验证?看内存监视就可以。(不过这里为啥多了一个我还没弄清楚,不过的确看到,三个函数地址后还有好几个数据,并且以nullptr<00 00 00 00>结尾)
    在这里插入图片描述
    因此,多态的实现原理就是通过virtual声明存在多态,之后生成虚表指针,管理虚函数。派生类通过重写基类的虚函数覆盖虚表中基类中三同的虚函数,不同的对象再通过调用同一函数,呈现不同的结果。

    上面这段话可能一时半会不太好理解,举个坐公交的栗子:

    #include <iostream>
    using namespace std;
    class Person {
    public:
    	virtual void ByBus() { cout << "票价:2元" << endl; }
    };
    class Student :public Person{
    public:
    	virtual void ByBus() { cout << "票价:0.6元" << endl; }
    };
    class Elder :public Person {
    public:
    	virtual void ByBus() { cout << "票价:0元" << endl; }
    };
    class Youth :public Person {
    public:
    	virtual void ByBus() { cout << "票价:1元" << endl; }
    };
    void Func(Person& p) {
    	p.ByBus();
    }
    int main() {
    	Person Wang;
    	Func(Wang);
    
    	Student Li;
    	Func(Li);
    
    	Elder Ma;
    	Func(Ma);
    
    	Youth Zhao;
    	Func(Zhao);
    	return 0;
    }
    

    4个不同身份的对象使用同一函数Func(),呈现不同结果:
    在这里插入图片描述
    我对多态原理的理解目前大抵就是这些了,如有不足,请各位指正!

    展开全文
  • 我们都知道,当要实现多态功能的时候,都会通过virtual关键字来讲基类中的函数变为虚函数,然后通过子类继承后重写就能够达到多态的效果。但是实际上,在其中,编译器也为我们做了很多的工作。 1.当编译器发现基类中...
  • java多态机制是什么

    2021-02-12 11:01:30
    java多态机制是什么java中实现多态的机制是依靠父类或接口的引用指向子类。从而实现了一个对象多种形态的特性。其中父类的引用是在程序运行时动态的指向具体的实例,调用该引用的方法时,不是根据引用变量的类型中...
  • 多态是一种不同的对象以单独的...大多数面向对象语言的多态特性都仅以虚拟函数的形式来实现,但C++除了一般的虚拟函数形式之外,还多了两种静态的(即编译时的)多态机制:1、操作符重载:例如,对整型和串对象应用...
  • 假如说要实现一个动物叫的方法,但是每一个动物的叫声不同,因此可以在方法中接收一个动物类型的参数,这样在同一个方法中,由于参数不同导致执行效果各异的现象就是多态。这也是为什么设计多态的原因。(总结就是同...
  • 同一行为具有不同的表现形式或形态的能力叫多态 子类需要继承父类 子类需要重写父类相关方法 向上转型:父类的引用指向子类的对象
  • java 接口实现多态

    2021-03-01 08:08:56
    Java 接口和多态练习 我们鼠标和键盘实现USB接口,那么我们鼠标和键盘就变成了USB设备,这时候我们就可以把它放到笔记本电脑里面去用 package com.biggw.day10.demo07; /** * @autho ... Java基础学习笔记八 Java基础...
  • 什么多态,JAVA 中多态 方法必须要被所在类或对象调用才有意义 若方法含有参数: 形参:方法声明时的参数。 实参:方法调用时实际传给形参的参数值。 JAVA里将实参数值传入方法的传递机制只有 值传递 在值...
  • Java多态实现原理

    2021-02-12 12:54:07
    0.前言多态在Java技术里有很重要的地位,在面试中也会经常被问到。多态的使用大家应该都比较了解,但是多态实现原理就有点抽象了,查了很多很多资料,连续几天断断续续的看,有时候看着...通过这篇文章相信可以帮...
  • Java 多态实现机制

    2021-02-27 13:02:54
    下面从虚拟机运行时的角度来简要介绍多态实现原理,这里以Java虚拟机(Java Virtual Machine, JVM)规范的实现为例。在JVM执行Java字节码时,类型信息被存放在方法区中,通常为了优化对象调用方法的速度,方法区的...
  • Java多态实现机制是什么Java中实现多态的机制是依靠父类或接口的引用指向子类,从而实现一个对象多种形态的特性,其父类的引用是在运行时动态的指向具体的实例,调用该引用的方法时,不是根据引用变量的类型中定义...
  • 多态的两种实现方法

    千次阅读 2021-03-14 03:13:35
    多态体现在父类和派生类之间,通过函数覆盖,实现在运行过程中动态调用函数。必要条件:(1)父类中将该函数声明为virtual(2)子类中完全一致的覆盖父类中的函数,要求返回值、函数名、参数都一致(3)通过指针或者借助于...
  • 当然,下面是“Observer”模式的具体示例,使用类和接口在记录器系统中完成多态行为:interface ILogger{public void handleEvent (String event);}class FileLogger implements ILogger{public void handleEvent ...
  • c++ 多态的定义和实现

    2021-03-09 11:08:37
    定义 多态就是不同继承类的对象,对同一消息做出的不同响应,基类的指针指向或绑定到...多态通过虚函数实现的,虚函数的首地址存在虚函数表中,虚函数表的地址存在含有虚函数的类的实例对象的内存空间中。 实现过程:
  • 在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度;今天我们再次深入Java核心,一起学习Java中多态性的实现。“polymorphism(多态)”一词来自希腊语,意为“多种...
  • 首先回顾一下什么是多态和多态实现的条件: 1.什么是多态: 当父类的指针或者引用指向子类的对象时,在使用父类指针或引用调用一个在父类和各个子类中同名的成员函数时,会根据指向的对象的类型来调用相应类中的成员...
  • python如何实现多态

    2021-01-14 09:34:42
    多态是指通过基类的指针或者引用,在运行时动态调用实际绑定对象函数的行为。对于其他如C++的语言,多态通过在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的...
  • Java如何实现多态

    千次阅读 2021-02-12 10:24:44
    1、多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个...
  • 继承实现多态

    2021-06-12 14:28:20
    在 Java 中有两种形式可以实现多态。继承和接口 继承例子: public class Parent { public void printPrice(){ System.out.println("这是父类方法"); } } public class ChildA extends Parent{ public v
  • 用最简单的一句话就是:父类型的引用指向子类型的对象。...首先讲下封装和继承:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面,他把实现的细节影藏起来了,比如你在java中去实现...
  • 使用C语言实现多态

    2021-07-30 10:57:22
    2.2.2C语言实现C++的继承与多态 一、C++的三大特性为:继承,多态,封装 1.1 继承 一个对象直接使用另一个对象的属性和方法。优点: 减少重复的代码。 继承是多态的前提。 继承增加了类的耦合性。 缺点: ...
  • 多态概念和实现

    2021-06-05 13:44:59
    多态的概念和实现 多态(因人而异)指的是同一时期方法调用,由于对象不同可能会有不同的行为。 多态的要点 1.多态的方法是多态,不是属性的多态(堕胎与属性无关)。 2.多态的存在要三个必要条件:继承、方法...
  • php同java一样是单继承,一个子类只能entends一个父类,多态一般用implements一个接口来实现。如下代码:有两个用户对象,student和teacher,两个对象都有name()和age()方法。/** php实现多态的两种方式*///定义接口...
  • PHP使用组合实现多态

    2021-04-12 17:44:05
    * WEB开发笔记 www.chhua.com 每日练习之PHP使用组合实现类的多态?*//*?* 类说明:某大学开两门课程,一个是PHP,一个是JAVA,规定不同的价格?*/abstract class lesson {//定义一个抽象基类?protected $lessonType;?...
  • java中如何实现多态

    2021-02-12 12:53:56
    标签:复习基础知识多态,就是重载和重写.重载发生在一个类中.重写发生在子类,意思就是子类重写父类相同名称的方法.刚学语言有的东西,不必搞得那么清楚,只有知道怎么用就行了,有的问题你要想真正把它搞得很懂,短时间...
  • C++ 多态实现和原理

    2021-05-23 05:51:18
    一、在编译期间实现多态多态是指在不同的条件下表现出不同的状态,C++中通过重载函数的方法可以在编译期间实现多态。在编译时编译器会根据参数列表的不同寻找合适的函数。int Add(int left, int right){return left ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 280,242
精华内容 112,096
关键字:

多态可以通过什么实现